Platform corrects the ADR-0039 rotation gate and proposes a distinct Sales workload policy
Platform response
Platform accepts Revenue's sequencing correction. Delivery readiness and Revenue enforcement are necessary, but they are not sufficient to rotate the root mint secret. Platform has corrected its ADR-0039 acknowledgment so rotation depends on every inventoried consumer migration, including Sales and Revenue's operator or staging callers, followed by Revenue enforcement readiness.
The corrected graph is:
event:root-mint-consumer-migrations-readyrequires Delivery migration, Sales migration, and retirement or migration of Revenue's root-mint operator callers.event:service-auth-root-rotation-readyrequires that aggregate consumer event plus Revenue subject-and-scope enforcement readiness.- Platform repeats the inventory immediately before rotation. Any newly discovered consumer extends the migration gate.
Root-mint inventory
Platform inspected source callers, local environment key names, all known Vercel projects, and recent production route traffic. Secret values were not read or recorded.
| Owner and environment | Root-mint evidence | Classification and required action |
|---|---|---|
| Platform production and preview | SERVICE_JWT_MINT_SECRET is configured |
Issuer-owned secret. Retain inside Platform through rotation. |
| Sales production and preview | PLATFORM_SERVICE_JWT_MINT_SECRET is configured. lib/platform/service-token-client.ts calls the legacy mint route for Revenue clients. |
Active deployed consumer. Migrate to a distinct Sales workload policy, remove every configured copy, and clear event:sales-workload-auth-migration-ready. |
| Revenue production and preview | SERVICE_JWT_MINT_SECRET is configured. Two standalone scripts call the smoke mint route. |
Explicitly retire or migrate both scripts, remove every configured copy, and clear event:revenue-root-mint-operator-callers-retired. |
| Delivery production and preview | No root-mint variable found. Delivery uses the workload exchange. | Migration event is already cleared. |
| Coaching, Finance, Growth, Portfolio, Web, Coordination, Them, and Them OS Vercel projects | No matching root-mint variable found. | No current environment-bearing consumer found. |
| Local checked-out environments | Platform, Sales, and Revenue contain root-mint variable names. | Remove consumer copies in Sales and Revenue as part of their migrations. Platform retains the issuer copy. |
The two Revenue scripts are scripts/adr-0032-staging-http-smoke.ts and scripts/repair-jennifer-holloway-june-trial-reservations.mjs. Neither is wired into a deployed route, Vercel cron, package script, or repository workflow. They still count as callers until Revenue explicitly retires them or moves them to the supported operator bearer or workload exchange.
Recent Platform production logs contained 87 workload-exchange requests, two direct legacy mint requests, and two smoke-mint requests in the inspected seven-day window. The legacy route accepts caller-selected subject values and does not provide trustworthy workload attribution, so the source and environment inventory remains authoritative until all consumer copies are removed.
Proposed Sales production policy
This policy is proposed for Sales and Revenue review. Platform will not enable it until both decision events in this memo are cleared.
| Field | Proposed value |
|---|---|
| Policy id | sales-production-to-revenue-v1 |
| Capability selector | revenue.sales-operations |
| Accepted workload subject | owner:jack-allreds-projects:project:sales:environment:production |
| Workload-proof audience | https://platform.sguildswim.com/api/auth/service-token/exchange |
| Issued subject | sales |
| Issued audience | revenue |
| Tenant | tnt_sguild |
| Organization reach | Canonical Sguild Organization only |
| Maximum lifetime | 300 seconds |
The proposed exact scopes are:
revenue.credit-accounts.readrevenue.orders.readrevenue.orders.createrevenue.orders.cancelrevenue.reservations.createrevenue.reservations.releaserevenue.sales-ordering.close
The proposed route map is:
| Sales operation | Revenue route | Required scope |
|---|---|---|
| Credit coverage read | GET /api/v1/credit-accounts/coverage |
revenue.credit-accounts.read |
| Invoice-link and credit-purchase reads | GET /api/v1/orders/invoice-link, GET /api/v1/orders/credit-purchases |
revenue.orders.read |
| Invoice-link creation | POST /api/v1/orders/invoice-link |
revenue.orders.create |
| Invoice cancellation | POST /api/order-externals/cancel-invoice |
revenue.orders.cancel |
| Reservation creation | POST /api/v1/reservations, POST /api/v1/reservations/atomic-multi-create |
revenue.reservations.create |
| Reservation release | POST /api/v1/reservations/{id}/release |
revenue.reservations.release |
| Sales ordering close | POST /api/v1/sales-ordering/close |
revenue.sales-ordering.close |
The inventory found no active Sales client for GET /api/v1/sales-ordering/orders/{id}, so this proposal does not add a separate scope for that route. It also excludes broad read, write, or wildcard authority and all Delivery-only correction, settlement, refund, grant, payment-capture, and lesson-consumption scopes.
Requested decisions
Sales should confirm that the caller and route inventory is complete, confirm the exact production Vercel workload subject, and clear event:sales-service-auth-caller-inventory-approved.
Revenue should confirm the route-to-scope map and enforcement ownership, then clear event:revenue-sales-service-auth-scope-map-approved. Revenue may request narrower scope names or route splits before approval.
Platform's implementation commitment remains gated on both decisions.
Migration sequence
- Sales and Revenue approve the caller inventory, workload identity, and exact route-to-scope map.
- Platform adds the approved policy to the service-auth contract, implements it, deploys it, and publishes a migration handoff.
- Sales migrates its shared Platform token client to Vercel OIDC exchange, keeps only in-process short-lived token caching, and fails closed when exchange fails.
- Sales proves each listed Revenue operation in production, removes all root-mint secret copies from production, preview, and local environments, and clears
event:sales-workload-auth-migration-ready. - Revenue retires or migrates both standalone root-mint scripts, removes its consumer copies, and clears
event:revenue-root-mint-operator-callers-retired. - Revenue independently proves subject, exact-scope, tenant, Organization, expiry, and denial enforcement, then clears
event:revenue-service-auth-enforcement-ready. - Platform repeats the full caller and environment inventory. Only when it is clean does Platform rotate the root secret, retire the consumer-facing legacy route, and prove every removed copy fails.
References
- ADR-0039:
adrs/ADR-0039-platform-issued-workload-identity.md - Revenue sequencing request:
2026-08-02-revenue-platform-adr-0039-rotation-sequencing-request - Revenue rotation gate correction:
2026-08-02-revenue-adr-0039-root-rotation-gate-correction - Platform acknowledgment:
2026-07-30-platform-adr-0039-workload-identity-ack - Service authentication contract:
contracts/service-auth/README.md