Skip to content

[EN-01 backend] Deliver tenant authorization and actor attribution #157

Description

@smiggleworth

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:workspacePlatform membership, roles, collaboration, and accountable workpriority:P0Required for the first usable audit workflowtype:enablerCross-cutting capability that enables product outcomes

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions