Backend child of #87. Milestone: R1 — Readiness program scoped. Deliver explicit authorization on every business endpoint, one tenant context per tenant-scoped command and query, with explicit self-service and platform-metadata route exceptions, actor snapshots, list and count filtering, consistent not-found behavior, and standalone/split-host proof. Prove the shared model through R1-01 and the R1-15 remainder in dependent capability PRs. Track evidence and close this child only when its backend acceptance criteria and exact-head CI are complete. Inherited non-UI dependencies: #84 (M0-A04), #126 (M0-A07), #60 (M0-D03), #123 (M0-D25), and #139 (M0-D28). M0-D24 is UI-only and remains on the product parent.
M0-A07 accepted
ADR 0009 is accepted (Jeff Repanich, 2026-09-22):
- Issuers. Several trusted OIDC issuers are validated directly, with no broker.
iss+sub binds once to a platform user, and linking two identities is explicit and needs proof of both.
- Authority. Token claims never carry membership or roles.
- Organization identifier.
tenant_id is opaque and is the only organization identifier. Organization-scoped routes are /api/v1/tenants/{tenant_id}/..., and body values are never trusted.
- Slugs. Slugs are readable and chosen by administrators. The API sends
Referrer-Policy: no-referrer, and slugs never appear in logs or telemetry. Retired slugs are never reassigned.
- Workspace. One workspace per organization.
- Tenant context. Context propagates through Fitz messages, jobs, caches, logs and telemetry, and consumers re-verify it.
- Leak tests. The ADR defines a layered cross-tenant leak test strategy. Each tenant-owned surface this story adds must include its own two-tenant, split-host proof.
This does not close or weaken this issue's own acceptance criteria.
Current acceptance boundary
The CI leak matrix must exercise every currently implemented tenant-owned HTTP and MCP surface, including its lists and counts, in standalone and split API/worker modes. Search, exports, artifacts, jobs, and notifications enter the matrix with the backend child that first implements each surface, as ADR 0002 requires; an absent route is not counted as tested. Preserve cross-tenant non-disclosure, restricted-row filtering before counts or pagination, and current authorization on every new path. PR #366 delivered the first durable ActorReference in Program events and HTTP/MCP views, plus a named system principal for Portia reactors; legacy Program events recover their member ID and display. This is partial: extend actor snapshots to other owning records and prove rename, identity replacement, and deprovisioning lifecycles. Operator-roster snapshots in #152 do not by themselves satisfy that shared contract.
M0-D25 authorization rule
The accepted client-tenancy decision allows verified-email self-service organization creation and restricts operator status to platform metadata and lifecycle authority. A firm-staff membership or team grant alone does not authorize client business records. R1-15 backend #152 closes that grant path for current and historical assignments, with HTTP/MCP denial proof across hosts. F1-07 backend #269 later introduces accepted, active ServiceEngagement assignment-based access and proves allow/revoke; EN-01 and R1-15 completion do not depend on that later capability. Apply the denial rule to requests, lists, counts, jobs, and split-host reads.
M0-A04 accepted
ADR 0002 is accepted (Jeff Repanich, 2026-09-22), with standalone and split API/worker authorization evidence in PR #159, fail-closed Portia composition in PR #325, and denied-action logging proof in PR #344. This removes #84 as a decision blocker; this backend child still owns complete first-consumer authorization, actor attribution, field/tenant behavior, and issue-specific acceptance evidence. The M0-D25 no-standing-access rule above remains in force; F1-07 later introduces engagement-assignment grants.
Backend child of #87. Milestone: R1 — Readiness program scoped. Deliver explicit authorization on every business endpoint, one tenant context per tenant-scoped command and query, with explicit self-service and platform-metadata route exceptions, actor snapshots, list and count filtering, consistent not-found behavior, and standalone/split-host proof. Prove the shared model through R1-01 and the R1-15 remainder in dependent capability PRs. Track evidence and close this child only when its backend acceptance criteria and exact-head CI are complete. Inherited non-UI dependencies: #84 (M0-A04), #126 (M0-A07), #60 (M0-D03), #123 (M0-D25), and #139 (M0-D28). M0-D24 is UI-only and remains on the product parent.
M0-A07 accepted
ADR 0009 is accepted (Jeff Repanich, 2026-09-22):
iss+subbinds once to a platform user, and linking two identities is explicit and needs proof of both.tenant_idis opaque and is the only organization identifier. Organization-scoped routes are/api/v1/tenants/{tenant_id}/..., and body values are never trusted.Referrer-Policy: no-referrer, and slugs never appear in logs or telemetry. Retired slugs are never reassigned.This does not close or weaken this issue's own acceptance criteria.
Current acceptance boundary
The CI leak matrix must exercise every currently implemented tenant-owned HTTP and MCP surface, including its lists and counts, in standalone and split API/worker modes. Search, exports, artifacts, jobs, and notifications enter the matrix with the backend child that first implements each surface, as ADR 0002 requires; an absent route is not counted as tested. Preserve cross-tenant non-disclosure, restricted-row filtering before counts or pagination, and current authorization on every new path. PR #366 delivered the first durable
ActorReferencein Program events and HTTP/MCP views, plus a named system principal for Portia reactors; legacy Program events recover their member ID and display. This is partial: extend actor snapshots to other owning records and prove rename, identity replacement, and deprovisioning lifecycles. Operator-roster snapshots in #152 do not by themselves satisfy that shared contract.M0-D25 authorization rule
The accepted client-tenancy decision allows verified-email self-service organization creation and restricts operator status to platform metadata and lifecycle authority. A firm-staff membership or team grant alone does not authorize client business records. R1-15 backend #152 closes that grant path for current and historical assignments, with HTTP/MCP denial proof across hosts. F1-07 backend #269 later introduces accepted, active
ServiceEngagementassignment-based access and proves allow/revoke; EN-01 and R1-15 completion do not depend on that later capability. Apply the denial rule to requests, lists, counts, jobs, and split-host reads.M0-A04 accepted
ADR 0002 is accepted (Jeff Repanich, 2026-09-22), with standalone and split API/worker authorization evidence in PR #159, fail-closed Portia composition in PR #325, and denied-action logging proof in PR #344. This removes #84 as a decision blocker; this backend child still owns complete first-consumer authorization, actor attribution, field/tenant behavior, and issue-specific acceptance evidence. The M0-D25 no-standing-access rule above remains in force; F1-07 later introduces engagement-assignment grants.