Grant model and shared permission-resolution algorithm #51
Labels
No Label
area:auth
area:docs
area:export
area:ops
area:storage
area:supply-chain
auth
backend
blocked
collab
deployment
docs
effort:L
effort:M
effort:S
frontend
plugins
qa
vs-nfd
vs-nfd:blocker
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: stwaidele/dorfteich#51
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The heart of the security model: one algorithm, implemented once, used by API, collab, and UI (permissions.md).
Scope
Prisma model
role_grantsper data-model.md with the structural constraints (pond_admin only pond-scope+user-subject; personal ponds single admin). Implement the resolution algorithm inpackages/shared/src/permissions/exactly as specified in permissions.md (specificity page > label(incl. ancestors) > pond; deny wins within a level; default-closed; Site Admin bypass; trash rule) with an exhaustive table-driven unit-test suite covering every worked example from the doc plus edge cases (multi-label conflicts, label-hierarchy inheritance, anonymous/public).Acceptance criteria
Technical notes
role_grants).Dependencies
Depends on #43.
Size: ~2 days
Conventions: English code/comments, clear human-readable code, no hard-coded UI strings (ADR 0012, add
deanden), permission checks only via the shared guard (docs/architecture/permissions.md). Read the referenced ADRs before starting.Implemented in
4d48d72(Claude Opus 4.8). Pipeline green (CI incl. all tests; CD deploy Test → smoke → promote Int — therole_grantsmigration + CHECK applied and the app booted healthy on both stages). #51 has no HTTP surface yet (theGrantsServiceis consumed by #52/#53), so it is verified by the exhaustive test suite plus the green deploy.Acceptance criteria
resolve.test.ts, table-driven).GrantsService.createGrantrejects pond_admin-on-label and a second admin on a personal pond (db test); a DB CHECK backs the pond_admin-scope rule.resolvePageCapability(action, ctx)— inputs are grants + labels + page + viewer, output a boolean; documented for API/collab reuse.Design notes
packages/shared/src/permissions/:resolvePageCapability(specificity page > label incl. ancestors > pond; deny wins; default-closed; Site Admin bypass) + trash helperscanAccessPage/canAccessTrashedPage(ADR 0013);grantValidationErrorfor structural validation.RoleGrantmodel + grant enums; unique on (pond, subject, role, scope); migration CHECK:role <> 'POND_ADMIN' OR (scope_type='POND' AND subject_type='USER').GrantsService(create with validation,grantsForPondreturning the shared resolver model) + DB↔shared enum mappers. Who may manage grants stays interim (owner/Site Admin) until #52.Next M5 issue: #52 (enforce permissions in API guards + retire interim access) — a larger security-critical refactor, handled as its own focused step.