Platform requires exact resource and recovery contracts before approving ADR-0053
Assignment ADR-0053/platform/001; coordinator 01a0e095-f279-7fd0-a8ef-92ce8f9547fc, host local; participant 01a0ff07-c6a3-7000-81a3-94f9960a4513. Reviewed Proposed ADR-0053 and its approval request at canonical commit 3225646710eb3073a4e8e5e5f8a6fb9f07eeb1cf. Platform supports the bounded direction but withholds formal acknowledgment until the exact contract package resolves the objections below. This memo deliberately has no acknowledges field. It approves neither another domain's financial predicates nor implementation or activation.
ADR-0052/platform/006 is handed back complete locally at bd002de011351d8ae81c5c87ba789c522b859924, with its passive loopback fixture preserved. This is the sole active design assignment in this participant chat. The four accepted ADR-0052 policies remain unchanged.
Source facts and minimum resource verdict
Platform's pinned source has three distinct surfaces. modules/person/routes/person.routes.ts requires a human session and calls alias-resolving getPerson. modules/person/repo.ts provides a raw exact-ID loader separately from its alias-resolving loader. modules/person-tenancy/repo.ts loads the exact (personId, organizationId) junction. The Prisma model has active/paused/inactive tenancy status, nullable Market and no tenant column. Organization has no enabled/status column; Member.status and disabledAt describe a human operator's membership, not a customer's PersonTenancy. Do not manufacture an Organization-enabled verdict, funded Market, human admission or role authority from these fields. mergePersons changes Person identity and reattaches externals; its inspected transaction does not reconcile PersonTenancy. A merged target's tenancy cannot be assumed to be the original tenancy.
Recommend a dedicated read-only operation whose proposed exact route is GET /api/identity/v1/person/{person_id}/scheduling-resource-verdict?organization_id={organization_id}. Permit precisely one Organization query member, no body, duplicate or unknown query members, listing, bulk lookup or caller-supplied tenant. Validate the authenticated tenant against the explicit served singleton tnt_sguild and Organization against the accepted singleton reach before lookup. Person and Organization tenancy are not stored with a tenant discriminator today; an env/default bootstrap fallback must not pretend to prove a row's tenant. A second tenant requires a separate data isolation decision and proof.
Recommend a closed successful verdict with only tenant_id, organization_id, requested_person_id, canonical_person_id, person_status, tenancy_status, new_write_eligible and evaluated_at. Person statuses are active/archived/merged, and tenancy statuses active/paused/inactive. A non-merged Person's canonical ID equals its requested ID. A merged Person may expose its one-hop canonical ID only under the exact authorized Organization association and verified lineage, while still returning the original requested ID and merged status. Missing, cyclic, chained or contradictory lineage is unverifiable, not a successful substitute. Never return contact data, names, age/minor fields, tenancy notes, role lists, other Organizations, Market funding or entire Prisma rows. The new sub-spec must explain this narrowly authorized relationship verdict without adding relationship data to CanonicalPerson's ten-field contract.
For a new write, new_write_eligible is true only for the exact requested active canonical Person, an existing matching Organization, and active tenancy on that exact pair. A merged input is ineligible even if its target is active. The consumer must correlate all echoed IDs and current service reach, and must never silently replace the Person in a command, hash, bind or receipt. Archived Person or paused/inactive tenancy can yield an authorized minimal negative verdict; missing Person/tenancy and a foreign association share a generic nondisclosing unavailable response. Authentication and request authorization precede lookup. Specify 401 for invalid authentication, 403 for scope/reach failure, 400 for malformed input, 405 for wrong method, a uniform 404 for an undisclosable/missing exact association, and an explicit unavailable envelope for authority/database/lineage uncertainty. No negative verdict proves financial noncommit.
Read Person, alias lineage and tenancy in one coherent Platform snapshot. Return Cache-Control: no-store; require a new read on each business attempt, without positive verdict reuse. evaluated_at is observation time, not a lease, CAS generation, immutable admission proof or promise that Platform state stays fixed through Delivery's commit. If owners require active identity at the exact remote commit instant, they must approve a real fence/lease and all identity invalidating-writer participation. A fresh HTTP read alone cannot provide that atomic guarantee, and no network call may remain inside a local database lock to imply it.
Historical access and identity compatibility
Keep eligibility separate from historical access. A current exact service/tenant/Organization entitlement plus a retained immutable admitted command, original association and receipt may authorize the owner's narrowly scoped historical recovery even after the initiating human loses access. Archived Person or paused/inactive tenancy must not by itself rewrite the admitted identity, fabricate noncommit, release protection, charge again or require a new human cookie. Conversely, a historical receipt or the new resource verdict alone is not authority to recover arbitrary keys. The owner authenticates and matches original provenance before any cached receipt or recovery disclosure.
Platform can supply current identity and retained association facts, not independently attest to a Delivery/Revenue admission it does not store. Recommend allowing a minimal historical identity read for a retained exact original Organization association, while returning new_write_eligible: false where appropriate. If the original tenancy or trustworthy lineage is absent, do not infer membership from a target's current row or a local Participant. Preserve uncertainty and recovery protection until an approved retained-association mechanism or owner-reviewed reconciliation can establish the original binding. Do not invent automated legacy eligibility. Define these cases explicitly in the contract rather than overloading an active-tenancy boolean as a historical authorization verdict.
Identity v1.5.0 sections 9.4 and 9.5 currently allow lazy alias resolution and require re-keying stored references, including historical snapshots. The new package must explicitly distinguish mutable operational/display projections from immutable admitted command, request and receipt bytes. Keep original immutable bytes and their digest; attach reviewed lineage separately. Preserve the existing Person-by-id behavior. If this changes an existing consumer obligation rather than clarifying the already-accepted immutable scheduling record type, declare the compatibility break and migration instead of silently treating it as minor.
Existing public GET /api/geography/catalog?market_id={marketId} filters active markets and active service areas and returns exact area-to-market association. It needs no new service policy. It establishes neither Person tenancy, Organization funding nor private-site access. Coaching eligibility and financial predicates remain their owners' decisions.
Proposed least-privilege policy inventory
The following are Platform's recommendations for owner review, not issued authority or finalized recipient routes:
| Policy ID | Caller proof project and output subject | Audience and sole capability/scope | Exact proposed route |
|---|---|---|---|
delivery-production-to-platform-scheduling-resource-v1 |
Delivery production, system:delivery |
platform, platform.identity.scheduling-resource.read |
GET /api/identity/v1/person/{person_id}/scheduling-resource-verdict, query exactly organization_id |
sales-production-to-revenue-close-recovery-v1 |
Sales production, sales |
revenue, revenue.sales-ordering.close.recover |
POST /api/v1/sales-ordering/close-recoveries |
revenue-production-to-delivery-scheduling-bind-compensation-v1 |
Revenue production, system:revenue |
delivery, delivery.scheduling.reservation.bind.compensate |
POST /api/v1/delivery/v1/lesson-holds/bind-compensations |
Production proof subjects must be exactly owner:jack-allreds-projects:project:<project>:environment:production, with issuer https://oidc.vercel.com/jack-allreds-projects and scalar audience https://platform.sguildswim.com/api/auth/service-token/exchange. Output issuer remains https://platform.sguildswim.com, tenant tnt_sguild, and Organization reach exactly [org_01900000-0000-7000-8000-000000000001]. Retain RS256, trusted nonempty kid and JWT typ, closed recipient claims, UUID jti, nonnegative integer times, nbf equal to iat, maximum 300-second lifetime and clock tolerance at most 30 seconds. Missing/unrelated well-formed scope remains 403 INSUFFICIENT_SCOPE; malformed authentication shape is 401; excess scope or well-formed wrong reach is 403. Each attempt obtains its own successful audited no-store issuance. No token/proof/cookie persistence or concurrent bearer/promise reuse, no implicit operator minting, preview subject, wildcard or inherited seven-scope Sales token authority.
The compensation evidence transport is a precise unresolved objection. An authenticated Revenue caller is not a demonstrated durable quiescence record. If Delivery verifies by a fresh Revenue read, recommend an additional narrowly scoped policy delivery-production-to-revenue-scheduling-bind-compensation-evidence-v1, subject system:delivery, audience revenue, sole selector/scope revenue.reservations.bind-compensation-evidence.read, for proposed GET /api/v1/reservations/{reservation_id}/scheduling-bind-compensation-evidence, query exactly organization_id, lesson_id, bind_intent_id, compensation_intent_id. This would be a fourth new policy supporting the three business capabilities. Owners must explicitly accept its count and exact response or instead specify an independently verifiable, bounded Revenue-owned attestation and its trust/key/version/rotation protocol. Do not silently broaden ADR-0052 bind-evidence scope or equate terminal abandoned evidence with authority for executable compensation. Platform does not approve either transport before the producer's schema and authority semantics are reviewed.
Request digest, admission settlement and compensation concerns
The original close route is POST /api/v1/sales-ordering/close; ordering v2.9.0 permits inline capture_token and link capture_id, uses an Organization-scoped Idempotency-Key up to 128 characters, and specifies offer-item and historical-booking normalization. Revenue's inspected close.routes.ts authenticates sales-ordering.close. The new recovery selector must not authorize that original route, replacement collection or generic Order reads. Revenue's inspected releaseBoundLockBestEffort calls hold cancellation and swallows failure; that is source evidence for needing a distinct bounded protocol, not evidence that compensation or financial quiescence is already correct.
Define one canonical versioned digest algorithm before approving recovery. It must bind tenant, Organization, original close key/namespace/version, Person, first Lesson, originating Lead and every original request value affecting idempotency or effects, using the original normalizer. Specify bytes, key order, Unicode, integers/currency, defaults, null versus absent, offer-item sorting and historical-booking normalization, not implementation-specific JSON.stringify. Bind capture source and the original credential association without retaining a reusable capture credential in Sales. A versioned domain-separated SHA-256 commitment to the opaque high-entropy capture value is a candidate, requiring owner/security review for both inline and link handles; simply deleting the credential before hashing does not commit to the original credential. Define sensitive-field treatment and audit/log exclusions. Revenue must independently compute and store the same digest at original admission, not trust a recovery caller's digest or replace its saved request with a reconstruction.
A recovery request should carry only closed, bounded original non-secret identity, digest/version and original close key, with exact correlation and no new offer, amount, payment credential or provider key. The key is the original operation identity, not a minted replacement recovery-close identity. Same key/different digest conflicts without disclosure or effects. A known unfinished admission resumes only its original durable preparation/dispatch/writeback state; an immutable terminal result stays terminal. Provider unknown and successful-provider/failed-writeback cannot become failed, absent, compensated or recharged because of an HTTP timeout. Revenue owns the financial interpretation and must specify its exact receipt/envelope.
Permanent never-admitted settlement must share the original close-admission serialization and permanent key identity, so a tombstone defeats every delayed original sender. A key prefix, matching current selections, valid Sales workload JWT or missing Revenue row does not independently prove eligible original new-command provenance. Define the independently verifiable Sales admission evidence and original non-secret association that make an unseen key eligible for settlement, plus obsolete caller and legacy journal barriers. This is an unresolved approval gate. Missing legacy records remain uncertainty, not executable recovery or noncommit. No fresh key/hold/collection follows settlement until separately authorized original-obligation resolution is established by its owner.
Compensation must bind tenant, Organization, original close/reservation/Lesson/Person, bind intent/key/digest, original ReceiptRef, compensation identity and protection generation. A changed identity or stale authority conflicts without cancelling or unlocking. Delivery owns its local atomic transition and receipt; Revenue owns the durable quiescence predicate and genuine incoming financial facts. Required specification includes evidence obtained outside local locks, same-generation recheck/CAS, repeated/lost response recovery, concurrent cancellation/bind/settlement exclusion, and protection transfer/retirement without a circular requirement to clear protection before safe compensation can execute. No generic cancellation, refund, forfeiture, Sales closure permission or inference from historical receipts. Platform supplies neither the financial predicate nor another owner's implementation commitment.
Version and proof gates before acknowledgment
Identity v1.6.0 and service-auth v1.9.0 are plausible additive targets only with new dedicated sub-specs, strict schemas/policy maps and unchanged existing canonical Person, session route and policy semantics. Recipient mode/history rules and the Identity 9.5 compatibility issue require an explicit disposition. An additive ordering recovery interface may remain minor only if the original close wire, replay and terminal outcomes remain unchanged for both inline and link. A mandatory original request field/header or changed terminal interpretation requires the explicit ordering major version described in the ADR. Scheduling compensation similarly needs its exact interface version and amendment to continuation rules, rather than implied authority in the existing v2 path. Any deprecation requires a safe migration and the standard maximum two-week window, without reopening unsafe legacy execution.
Before Platform can acknowledge, assemble the exact verdict and history schema, digest/admission/tombstone/receipt protocol, compensation verification transport and its policy count, owner-defined financial/protection semantics, error/method/path/query taxonomy, compatibility versions and release plan in one reviewed package. Obtain the owning domains' own approvals. No implementation commitment is declared by this review.
Required later proof gates are signed positive and closed-shape denial vectors for every new selector; exact method/query/body and nondisclosing alias/tenancy cases; coherent snapshot and invalidating-identity interleavings with explicit freshness limits; original inline/link response loss without credential retention; before-admission recovery racing delayed original sends; changed digest/key/Organization and legacy quarantine; provider-unknown and writeback-failure recovery; repeated/lost compensation responses and all-writer/protection-generation races. Use real owner handlers, fresh keys and isolated persistence, with count and stable row-content-hash denial checks and external dispatch observation. Label synthetic workload identities, mocked resource/provider predicates and recording transports. Static schemas or the existing local fixture establish none of these new runtime/production gates. New issuance and recipient admission stay fail closed until the approved package and separately authorized release evidence exist; already-issued offline JWTs retain their bounded residual lifetime.
Evidence and publication boundary
Source basis: Platform commit bd002de011351d8ae81c5c87ba789c522b859924, specifically modules/person/{dto,repo,service,schema}.ts, modules/person/routes/person.routes.ts, modules/person-tenancy/{dto,repo,service}.ts, prisma/schema.prisma, modules/bootstrap/tenant.ts, modules/geography/routes/catalog.routes.ts and modules/service-auth; read-only Revenue checkout C:/Users/jallr/.codex/worktrees/revenue-adr0052/revenue at 3912d4ab178ab6cfc3fd798a98e78aaae3d4d5ba, with modules/sales-ordering-surface/{service.ts,routes/close.routes.ts}; Delivery's docs/adr0052-upstream-authority-dependencies.md; Identity v1.5.0, service-auth v1.8.0, ordering recovery v1.0.0 and scheduling compatibility v1.0.0.
Live Platform inbox and ledger were refreshed during this review. No implementation or publication commitment was completed. Only this owner response is prepared in the permitted coordination clone. No other owner's files, contracts, ADR, runtime, signing keys, database, passive fixture or production settings were changed. Root is sole publisher and owns eventual indexing/freshness after publication; this participant did not independently publish or index. No duplicate task acknowledgment is requested.