Round off permissions-as-code (#13) for real operation: today domainId is a hand-supplied number, grant adoption shipped but is broken for non-group scopes (#49), and the name→authId catalog (src/permissions/catalog.json) is a one-off HAR-trace artifact of a single CT version with no staleness detection. Part of the Phase 6 epic.
Scope
Acceptance criteria
Round off permissions-as-code (#13) for real operation: today
domainIdis a hand-supplied number, grant adoption shipped but is broken for non-group scopes (#49), and the name→authId catalog (src/permissions/catalog.json) is a one-off HAR-trace artifact of a single CT version with no staleness detection. Part of the Phase 6 epic.Scope
{ group: "mainz_kids_lead", role: "Leiter" }/{ groupType: "ministry_team", role: "Leiter" }and resolve to the numericdomainIdlive. Prerequisite: freeze thegroup_roledomainId semantics (Phase 5 spec open item 2 — role-definition id vs per-(group,role) pairing id; the code comment says pairing id, confirm on eqrm-dev and pin with a test). The shared resolver this needs exists (feat: portable configs — logical references instead of numeric CT ids (shared resolver) #20, merged).Adopt grants— done (PR feat: ct adopt grants — emit paste-ready permission config from live rows (#25) #45):ct adopt grants <domainType> <domainId>reads live user-authored grants (baseline/inherited excluded) and emits thegrants:block. Residual bug: churchdb grants scoped to non-group dataIds are misclassified — tracked as bug(permissions): ct adopt grants assumes every scoped dataId is a group #49, blocks plan-to-no-op on prod.catalog.jsonfrom the legacychurchauth getMasterDatacall against a live instance; record the CT version the catalog was captured from inside the file;ct planwarns when the instance version ≠ catalog version or when an actual grant carries an authId unknown to the catalog (today that's an unexplained diff).type: "revoke"authoring (valid forgroup_roleonly —GrantTuplealready models it, DSL never emits it).Acceptance criteria
ct planno-op.