ADR-0003 — One data-ladder Scope type
- Status: Accepted + landed (2026-06-22, commit
0547346f3). - Enforced by:
scripts/arch-fitness.shcheckone-scope-type(hard-zero).
Context
Section titled “Context”One concept — the tenancy ladder — was declared as five or six different Go
types with divergent value strings: core/scope.Scope, a duplicate
config.Scope, vault.SecretScope (broadest tier spelled "system"),
legacy vault.Scope (spelled "base"), and backup.Scope (with a dead sixth
"local" tier). The same broadest tier was "global"/"system"/"base"
depending on the module, bridged by hand-written conversion functions. A row
written by one module and read against another’s ladder could silently
mis-classify — duplicate-implementation syndrome on a load-bearing enum.
Decision
Section titled “Decision”core/scope.Scope is the single data-ladder type:
{global, tenant, environment, stack, deployment}, broadest tier "global".
config.Scope,vault.SecretScope, legacyvault.Scope, andbackup.Scopeare deleted; their bridge functions (scopeToSecretScopeetc.) go with them.- The dead
"local"tier is dropped. auth.Scopeis renamedAuthScopeand kept separate — it is an RBAC resource-class marker (with a""auto value), not a data ladder, and never converts to/from the tenancy ladder.- The vault KV path layout is preserved: the broadest tier serializes to the
"system"URL segment via a single presentation mapping (not a parallel type), and"system"/"global"/"base"are accepted as read synonyms. - The DB
scopecolumn’s broadest written value moves"base"→"global"(pre-1.0 hard migration; free-string column, no schema change / no data migration).
Consequences
Section titled “Consequences”- One precedence/
Cascade/Rankdefinition; no cross-type conversions to drift. - A typo’d or divergent tier is now a compile error, not a silent mis-classify.
- A new
type Scope stringanywhere outsidecore/scopefails the build.
shc@docs:~$