Revenue approves ADR-0039 with an explicit Delivery scope map and fail-closed verifier requirements
Revenue acknowledges ADR-0039 and approves Option A without revision to the chosen architecture. Platform should remain the only holder of signing material and the root mint secret. Vercel-hosted callers should exchange Vercel OIDC workload proof for short-lived, policy-bound Platform service JWTs. Revenue should enforce the authority Platform grants instead of treating a valid signature as sufficient authorization.
The current Revenue verifier confirms the gap described by Delivery. It verifies
signature, issuer, audience, expiration, sub, and tenant_id, but its auth
context carries only subject and tenant. Authenticated routes do not yet enforce
subject or scope. ADR-0039 is therefore the right boundary repair, not only a
credential-rotation improvement.
Required service-auth contract
The shared service-auth contract must make iss, aud, sub, tenant_id,
iat, nbf, exp, jti, and scope required claims and define one
canonical scope serialization. Delivery tokens use aud = revenue and
sub = system:delivery. Platform policy, not exchange request fields, fixes
tenant and organization reach. The initial token lifetime should be no more
than five minutes.
Revenue will accept only the contract's named signing algorithm, initially
RS256, and will continue to validate issuer, audience, and expiration through
Platform's JWKS. Missing or invalid authentication remains a 401. A valid
token that lacks the required subject, tenant, organization reach, or scope is
a 403 with a stable insufficient_scope or forbidden code. The contract
must define JWKS rotation overlap, clock tolerance, and the behavior for an
unknown kid.
Revenue authorization logs should record the decision, jti, subject, audience,
tenant, organization, scopes, route or operation, request id, and correlation or
idempotency key when present. They must never record the bearer token or raw
workload proof.
Initial Delivery scope map
Revenue approves the following initial operation scopes for
system:delivery. Scope names are exact contract vocabulary, not descriptive
labels:
revenue.reservations.readfor lock-state and legacy-id-map reads.revenue.credit-accounts.readfor coverage reads.revenue.orders.readfor open and completed credit-purchase reads.revenue.payment-methods.readfor card-on-file availability.revenue.lesson-outcome-corrections.previewfor correction preview.revenue.reservations.createfor Delivery-owned reservation creation.revenue.reservations.releasefor the published release command.revenue.reservations.forfeitfor the published forfeit command.revenue.orders.createfor additional-credit purchase and invoice creation.revenue.payments.capture-handle.createfor the published capture-handle deposit.revenue.service-recovery-credits.grantfor the published recovery-credit grant.revenue.refunds.initiatefor the published refund composition.revenue.lessons.consumefor the existing lesson-settlement command.revenue.lesson-outcome-corrections.applyfor the guarded correction apply command.
Platform policy must not grant Sales ordering, operator administration, catalog
mutation, provider configuration, or unrelated Revenue scopes to
system:delivery. Revenue will map each protected route to one or more required
scopes and will also allow only the subjects named for that operation. A broad
revenue.read, revenue.write, or wildcard scope is not an acceptable
substitute for this first migration.
Migration and cutover
The additive order in ADR-0039 is correct. Platform first deploys the exchange and contract. Revenue then deploys subject and scope enforcement with explicit compatibility limited to the routes still awaiting caller migration. Delivery migrates and proves each read and command path. As each route is proven, Revenue removes no-scope admission for that route. There must be no permanent rule that treats a missing scope claim as full authority.
Delivery's production proof should cover every operation listed above that the
deployed client actually invokes, plus audit:locks. Revenue should verify both
allow and deny cases: the intended Delivery token succeeds, a token for another
subject fails, a token missing the operation scope fails, and a token outside
the allowed tenant or organization reach fails. After all known callers have
cut over, Platform rotates the root mint secret and the old issuance path stops
being a consumer integration surface.
No new Revenue implementation commitment is declared while ADR-0039 remains Proposed. After acceptance and publication of the shared service-auth contract, Revenue should carry the verifier and route-policy implementation in the accepted-decision follow-up.
References
- ADR-0039:
adrs/ADR-0039-platform-issued-workload-identity.md - Delivery proposal:
2026-07-30-delivery-adr-0039-workload-auth-proposal - Revenue verifier:
lib/auth/platform-jwt.ts - Revenue lock-state read API:
docs/api/lock-state-read-v1/README.md - ADR-0036:
adrs/ADR-0036-operator-auth-rail-for-domain-web-apps.md