Version Policy — @yetdapay/* and @yetdapay/* packages
Reading guide
All SDK and CLI packages are pre-1.0. The policy distinguishes package SemVer from the implicit v1 license wire contract, which has no version negotiation.
Use the compatibility matrix before upgrading a client or server; do not infer compatibility from package version alone.
Status:
IMPLEMENTED(policy document) — written for the d7 release candidate. All packages are pre-1.0; this policy is honest about what that means: no stability guarantees are claimed yet, and the wire contract has no negotiation mechanism.
1. Scope
| package | path | current version | publish state |
|---|---|---|---|
@yetdapay/cli | tools/yp | 0.2.0 | private: true — unpublished by design (carries in-repo vendored sources); npm pack / npm i -g <tgz> work |
@yetdapay/mcp | tools/devpay-mcp | 0.1.0 | private: true — unpublished by design |
@yetdapay/license-web | sdk/license/web | 0.1.0 | private: false, UNLICENSED — pack-verified, not published |
@yetdapay/license-server | sdk/license/server | 0.1.0 | private: false, UNLICENSED — pack-verified, not published |
@yetdapay/license-nuxt | sdk/license/nuxt | 0.1.0 | private: false, UNLICENSED — pack-verified, not published |
@yetdapay/sdk | sdk/ | 0.1.0 | private: true — copy-in source bundle (files: TS/Vue/React sources), not a build artifact |
yetdapay-mcp (Rust) | mcp/ | 0.1.0 | cargo binary, repo-SHA-versioned |
yetdapay-mcp-gateway | mcp/gateway/ | 0.1.0 | Worker script, repo-SHA-versioned |
Sibling packages that cannot resolve each other from a registry use file: specifiers — see §4.
2. SemVer policy (pre-1.0 interpretation)
We follow Semantic Versioning 2.0.0 with the standard pre-1.0 caveat, stated explicitly so nobody has to guess:
0.MINOR.PATCH— the major version stays0until the wire contract (§3) reaches v1-stable and the public JS/TS API of each package is declared stable in this document.- Minor (
0.x.0) bumps may contain breaking changes. This is legal SemVer for0.x, and we will use it: a breaking API or wire change before 1.0 increments MINOR, never PATCH.@yetdapay/cli0.1.0→0.2.0 (platform command surface added) is the first example. - PATCH (
0.x.y) is reserved for backwards-compatible fixes — bug fixes, doc corrections, test/CI repairs that change no public signature and no wire bytes. - No breaking change may land silently. Any
0.x.0bump that breaks an interface documented ininterface-contract-matrix.mdmust be recorded inCHANGELOG.mdunder a### Removed/### Changedheading with a migration note. "It is only 0.x" is not a reason to skip the changelog entry. - 1.0.0 criteria (not yet met): wire contract v1 declared frozen;
@yetdapay/license-*public API declared stable; at least one executed compatibility run ofsdk-worker-contract.test.mjsagainst the candidate backend recorded in release evidence.
3. Wire contract versioning
| contract | version | negotiation | notes |
|---|---|---|---|
Entitlement/PoP wire (/api/v1/licenses/{activate,capability,execute,status}, JWS claims, DPoP-style proof) | v1 | none — there is no version field in tokens, headers, or envelopes (known-limitations.md §3.2). Compatibility is "same contract generation", honestly not negotiated. | |
Commerce REST (/api/v1/public/integrations/*, hosted /h/*, feedbacks/donations POST) | unversioned path prefix /api/v1/ | none | same payload on Axum be/ and be-cloudflare since d3 (migration 018) |
| MCP protocol (local stdio + remote gateway) | MCP 2024-11-05 | MCP protocol-version handshake only | tool surface is unversioned; tools are additive so far |
Evidence record schema (yp protect verify output) | schema_version: 1 | explicit field | the only artifact with a real version field today |
Wire v2 candidates already on record (any of these landing = contract v2, and SDK MINOR bumps on both sides): aud/tenant_id claims in Worker-issued entitlements, error-code convergence (INVALID_PUBLIC_JWK, CAPABILITY_INVALID, PAYLOAD_TOO_LARGE, INVALID_STATUS), and any token-format change. See interface-contract-matrix.md §5 and known-limitations.md §3.8.
4. SDK ↔ backend compatibility matrix
Derived from interface-contract-matrix.md §1–§4 (single contract reference). "Compatible" below means: an executed pairing exists, or the pairing is one config line via createWorkerConfig().
| client | Axum be/ | be-cloudflare Worker | self-hosted @yetdapay/license-server |
|---|---|---|---|
@yetdapay/license-web 0.1.0 | n/a — Axum has no PoP entitlement plane (legacy records only) | ✔ wire v1 via createWorkerConfig() (activatePath=/api/v1/licenses/activate, iss=devpay-lic); verified by sdk-worker-contract.test.mjs (10 checks, loopback wrangler dev) | ✔ default config (activatePath=/api/license/activate, iss=devpay); Scenario C (examples/license-server) |
@yetdapay/license-server 0.1.0 (as verifier) | n/a — different plane | claim parity via createWorkerConfig() (iss=devpay-lic, aud unset, tenant_id tolerated); remaining deltas are the documented error-code fold-ins (matrix §2) | native |
@yetdapay/license-nuxt 0.1.0 | n/a | wraps web+server above — same rows | same |
@yetdapay/sdk 0.1.0 | ✔ donation/feedback REST — Scenario D executed locally (seeded dev-auth sqlite) | ✔ endpoints exist since d3 (migration 018); deployed round-trip NOT_VERIFIED — all executed evidence is loopback | n/a |
@yetdapay/cli 0.2.0 platform commands | ✔ auth/project/license/integration (dev-auth X-Dev-User model) | ✔ incl. integration check (d3 port); license detail probes (/bindings, /usage) Worker-only | n/a |
@yetdapay/mcp 0.1.0 | local protect tooling — verdicts pass through yp --json unchanged | same | n/a |
| remote MCP gateway 0.1.0 | n/a (targets the Worker) | 20 tools (10 configure/validate + 10 seller-scope/public reads); Bearer passthrough; seller round-trips NOT_VERIFIED against deployment | n/a |
Peer resolution for unpublished siblings
@yetdapay/license-nuxt declares peerDependencies on @yetdapay/license-server ^0.1.0 and @yetdapay/license-web ^0.1.0 (license-web marked optional — the server-only path works without it). Because none of the @yetdapay/* packages is published to a registry, consumers cannot resolve these peers from npm. The supported install pattern today is file: (or a packed .tgz) against a repo checkout, exactly as examples/license-server/package.json does:
"dependencies": {
"@yetdapay/license-server": "file:../../sdk/license/server",
"@yetdapay/license-web": "file:../../sdk/license/web",
"@yetdapay/license-nuxt": "file:../../sdk/license/nuxt"
}2
3
4
5
npm/pnpm dedupe file: installs to a single copy per path, so the license-nuxt peer requirement is satisfied by the same checkout. When real publishing is approved, the ^0.1.0 peer ranges will resolve normally; until then registry installs of license-nuxt will warn/fail on peer resolution — that is expected, not a bug.
5. Breaking-change policy (pre-1.0)
- Breaking changes are allowed on MINOR bumps but must be (a) intentional, (b) recorded in
CHANGELOG.md, (c) reflected ininterface-contract-matrix.mdwhen they touch wire bytes, claims, or error codes. - A change to emitted/verified entitlement claims, proof shape, or activation request/response is a wire change, not an implementation detail — it requires updating the matrix and the
sdk-worker-contract.test.mjsexpectations in the same wave. - Deprecation before removal is preferred even in 0.x: keep the old field/route for one MINOR where feasible (the d5b donation
donor_name/messagefix chose optional + server-side default precisely because it was the least-breaking direction). - Fail-closed posture is part of the contract: tightening a check (e.g. unknown
status→REVOKED) is a fix, not a break; loosening one is a security change needing INDEPENDENT_SECURITY sign-off.