ADR-0012: Permission-Based Authorization and System Bootstrap¶
- Status: accepted
- Date: 2026-06-17
- Deciders: Nicolas Burri
- Relates to: ADR-0002, ADR-0003, ADR-0004, ADR-0010, ADR-0011; GAP-03
- Refined by: ADR-0027 (scope/mandator/catalogs/authz are control-plane, permission-governed, not under content RLS), ADR-0121 (admin ≠ content: the recorded, narrow deviation at project level), ADR-0128 (the GLOBAL cascade narrowed to ADMINISTRATIVE-class permissions), ADR-0129 (role identity from a GLOBAL assignment acts in GLOBAL alone)
Context¶
Authentication is decided (ADR-0011), and review policies govern document life-cycle transitions (ADR-0003). What is undefined is functional and administrative authorization: who may create a scope, manage the catalog, assign roles, configure a review policy (REQ-CAT-001's "authorized users" hole). A fresh installation also has a chicken-and-egg bootstrap problem (assigning roles needs an admin, but none exists yet), and — per ADR-0010 — should come up ready to manage the organization's own QMS.
Decision¶
A closed set of permissions, configurably mapped to roles (mirroring ADR-0003's fixed-mechanism / configurable-policy stance):
- The system defines a fixed, closed set of named permissions spanning content/
functional capabilities (e.g.
CREATE_DOCUMENT,EDIT_DRAFT,DERIVE,VIEW,ASK_LLM) and administrative ones (e.g.ASSIGN_ROLES,CONFIGURE_REVIEW_POLICY,ACTIVATE_CATALOG_ENTRIES,MANAGE_LLM_POLICY,MANAGE_SCOPES,MANAGE_CATALOG,MANAGE_USERS,EXPORT_BACKUP). New permissions require code; their assignment does not.
(Amended 2026-07-29, V073: this list originally namedCREATE_SCOPEandCREATE_MANDATOR. Both were minted by this ADR's vocabulary sweep before any write surface existed and were never enforced anywhere; when ADR-0097 built that surface it chose ONE permission,MANAGE_SCOPES, covering all four provisioning acts. V071 backfilled everyCREATE_SCOPEholder withMANAGE_SCOPES, V073 deleted the two dead rows, and the enumeration above now reads as the closed set actually is.)
(Amended 2026-08-05, V078: this list also namedUPLOAD,SEARCHandVIEW_AUDIT. V077's description rewrite forced an enforcement audit of the whole catalog and found seven permissions gated by no surface. These three were retired because their acts DO ship and are deliberately gated by something else — search byVIEW+ scope isolation, upload byEDIT_DRAFT, the audit trail and scope activity byVIEWin the scope. RetainingVIEW_AUDITwould not have been neutral: it would have narrowed a disclosure boundary decided the other way, an unproven variation point. The four remaining reserved names —ASK_LLM,MANAGE_LLM_POLICY,EXPORT_BACKUP,ERASE_PERSONAL_DATA— were KEPT: they name capabilities the roadmap owes, not gates another permission already covers.) - Each catalog role is configurably mapped to a permission set (extends ADR-0004);
changing the mapping requires
MANAGE_CATALOG. - Scope-cascading effect: holding a role in a scope grants its permissions within that scope and its descendant scopes. A role held at the global scope grants them installation-wide (system administration); at a mandator scope, across that mandator's projects (delegated administration); at a project scope, locally.
- Admin and content permissions are independent. System-administration permissions do not implicitly grant content read; reading a scope's documents requires a content permission effective there. The default/recommended catalog keeps content permissions project-local, so an installation administrator does not implicitly see customer data — preserving mandator separation (STR-003).
Amendment (2026-09-04 — recording ADR-0121, ADR-0128 and ADR-0129). The two bullets above are narrowed at the GLOBAL scope, and a reader of this ADR alone would otherwise learn a separation-relevant falsehood (found by the 2026-09-04 ADR-coherence review as its first hard contradiction). What now holds:
- The cascade is classified, not universal. From an assignment at the GLOBAL scope, only ADMINISTRATIVE-class permissions cascade installation-wide; CONTENT-class permissions from a GLOBAL assignment are effective in GLOBAL alone (ADR-0128). "A role held at the global scope grants them installation-wide" is therefore true of the administration half only. The MANDATOR-anchor and PROJECT readings above are untouched.
- Role identity cascades the same way. Workflow authority — the role-gated approve/release/revoke acts, which carry no permission at all — likewise stops at GLOBAL when it comes from a GLOBAL assignment (ADR-0129). The MANDATOR-anchor role cascade is deliberately kept.
- "Admin ≠ content" stays absolute at GLOBAL, and has one recorded exception below it. ADR-0121 §"ADR-0012 is amended in scope, not repealed" grants the seeded Project Administrator read-class content (VIEW, VIEW_TRACEABILITY) at project level, behind that project's own activation + staffing act — a scoped, argued deviation (cross-tenant vs. within-tenant), not a general relaxation. The classification is machine-checked (
PermissionClassificationTest), so the vocabulary polices itself.The doctrine these three amendments serve is the one this ADR wrote down: an installation administrator does not implicitly see customer data. They make it structural where this text left it to catalog convention. - Boundary with review policies: life-cycle transitions (submit/approve/release/ revoke) remain governed by review policies (ADR-0003); the permission model governs all other functional and administrative actions.
Bootstrap & onboarding:
- A deployment-configured bootstrap identity (an OIDC subject/email) is granted system administration idempotently on startup — initial setup and break-glass recovery. The system shall not allow removing the last administrative capability and leaving none.
- On first initialization the system auto-creates the global base scope and an internal mandator with a "QMS Operations" scope (ADR-0010).
- Onboarding a project = create scope → activate catalog roles/types → staff roles → configure review policies, each gated by the corresponding permission.
Options Considered¶
- Built-in administrative roles with fixed permission sets (rejected): predictable and minimal to validate, but not reconfigurable — organizations would have to staff our admin roles instead of reusing their own, the kind of imposed-role friction the project set out to avoid.
Consequences¶
- Schema: a
permissionreference set (enumerated/closed), arole↔permissionmapping (extends the catalog), and role assignments per scope (ADR-0004). The deferredmandator.internalflag (ADR-0010) is built together with this mandator/administration management. - Scope-context resolution (ADR-0009/0011) must expand a held scope to its subtree when computing the authorized scope set and effective permissions.
- Larger authorization surface to validate (CSV); the closed permission set keeps it bounded, and the break-glass bootstrap prevents lock-out.
- All administrative actions are audited (REQ-AUD-001).
Requirements¶
Introduces STR-017 and the REQ-ADM group (pending requirements baseline v1.1).