shoc-backend/docs/adr/0001-work-order-single-org-scope.md

66 lines
2.6 KiB
Markdown
Raw Normal View History

# ADR 0001: Work-order media uses single-org scope (board-aligned)
## Status
**Superseded** (2026-08-06) by the SH-221 media slice in PR #47:
- `WorkOrder.AccountId` / `ApplicationUser.AccountId` schema keys
- JWT `account_id` claim emitted from `ApplicationUser.AccountId`
- Media loads filter via `ApplyBaseScope` + `ApplyAccountScope` when the claim is present
Board, detail, and search outside media still use base scope only until the
remainder of [SH-221](https://luby-us.atlassian.net/browse/SH-221) lands.
## Context (historical)
SH-116 requires that cross-tenant, unauthorized, and out-of-scope media access
be rejected without metadata disclosure. When this ADR was Proposed, the
work-order domain had no `TenantId` / `CustomerId` / `AccountId` on
`WorkOrder` or `ApplicationUser`, and JWT issuance emitted only identity/role
claims. Media authorization matched the board via `ApplyBaseScope` plus
role/assignee checks.
## Decision (historical — Proposed interim)
Until real tenant enforcement existed, work-order media authorization matched
the board: `ApplyBaseScope` + claims-derived roles/assignee. That interim is
no longer the media contract.
## Current media contract (superseding)
1. **Organization boundary** = `ApplyBaseScope` (non-deleted, non-template).
2. **Account boundary** = when the principal has claim `account_id`, media
queries require `WorkOrder.AccountId == claim`. Cross-account → stable
`NotFound` / null (no disclosure).
3. **Org-wide staff** = staff principals **without** `account_id` keep base
scope only (explicit claims rule).
4. **Authorization at service entry** from claims: staff roles may read/mutate
any resulting work order; role `User` only when `AssignTo == actorId`;
delete remains staff-only.
## Consequences
- Cross-account media tests are required for principals that carry `account_id`.
- Board/search/detail without account filtering remain a SH-221 follow-up.
- This ADR no longer grants an exception to §2 for media; the claim+FK path is
the enforcement.
## Excepted rule
None for media (superseded). Hard rule **server-derived tenant scope**
(`ARCHITECTURE_AND_CODE_QUALITY.md` §2) is enforced for media via `account_id`.
## Review / expiry
Re-review when SH-221 closes remaining board/search/detail account filters, or
by **2027-02-04**.
## References
- SH-116 — Completion document: fields + media categorization
- SH-221 — Server-derived tenant/customer scope for Work Order domain
- PR: Sea-Haven-Industries/shoc-backend#47
- `WorkOrderBoardQueryFilters.ApplyBaseScope` / `ApplyAccountScope`
- `WorkOrderMediaAuthorization`
- `ARCHITECTURE_AND_CODE_QUALITY.md` §2, §10