Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLI
Assigneesstack72

Relationships

↑ child of #662

#667 serve-auth: access bounded context — Grant, Group, and shared value objects

Opened by stack72 · 6/17/2026· Shipped 6/17/2026

Parent

Sub-issue of #662 (serve authentication & authorization). Layer 1, items 1 + 2.

Summary

Create the domain/access/ bounded context with the Grant and Group aggregates, their built-in models, and the shared value objects they depend on. This is the foundation of the authorization system — all other access-related work (CEL environment, decision service, CLI, enforcement) builds on top of it.

What to build

Shared value objects

These are used by both Grant and Group and should be established first:

  • Principal — an authenticated identity: { kind: user | worker, id: string }. Used as grant subjects, group members, and the acting identity in access decisions.
  • Subject — what a grant targets: { kind: user | group | idp-group, name: string }. Distinct from Principal because grants can target IdP-asserted groups that aren't locally-managed principals.
  • ResourceSelector — what a grant covers: { kind: workflow | model | data | access, pattern: string }. Patterns use name-globs over scoped names (@collective/*).
  • Action — what a grant permits: run | read | write | admin.
  • Effectallow | deny.
  • GrantSource — how a grant was created: method | file | config | extension:<name>.

Grant aggregate (aggregate root, built-in model)

Schema:

  • id — unique identifier
  • subjectSubject
  • effectEffect
  • actionsAction[]
  • resourceResourceSelector
  • condition — optional CEL expression string (stored as string; validation against the CEL environment happens in a sibling issue)
  • stateactive | revoked
  • sourceGrantSource
  • createdBy — principal who created the grant
  • createdAt — timestamp

Model methods:

  • create — create a new grant, validates subject/resource shapes
  • revoke — transition active → revoked (state change, never a delete, history retained)
  • list — query active grants, filterable by subject and resource

Group aggregate (aggregate root, built-in model)

Schema:

  • name — unique group identifier
  • members — array of principal references (user:<sub>)
  • createdBy — principal who created the group
  • createdAt — timestamp

Model methods:

  • create — create a new named group
  • add-member — add a principal to the group
  • remove-member — remove a principal from the group
  • list — list all groups
  • members — list members of a specific group

Key invariants

  • Revocation is a state transition, never a delete — history is the audit trail
  • Generic data writes must not create/alter access records — the built-in models own their data as model-method (the existing OwnershipValidationError pattern). For access types this is security-critical and must be pinned by tests.
  • Resource selectors reuse the @collective/name scoping convention from extension manifests
  • Groups are locally-managed — membership is stored in the model. This is distinct from IdP-asserted groups (idp-group:<name>) whose membership comes from the provider's userinfo response and is never stored locally. The two must not be confused.
  • The condition field is stored as a string — validation against the CEL environment happens in a separate issue (layer 1, item 3)

Scope

  • Pure domain code in src/domain/access/ — no enforcement wiring, no CLI commands
  • No dependency on OAuth, TLS, or other auth machinery
  • Fully testable in isolation

Out of scope

  • AccessDecisionService (layer 1, item 4 — depends on this + CEL environment)
  • Sealed CEL grant environment (layer 1, item 3)
  • CLI commands (layer 2)
  • Enforcement wiring (layer 5)

References

  • Enrollment token model for the built-in model pattern: src/domain/models/worker/enrollment_token_model.ts
  • Worker model: src/domain/models/worker/worker_model.ts
  • Step lease model: src/domain/models/worker/step_lease_model.ts
  • Extension collective validator for scoping patterns: src/domain/extensions/extension_collective_validator.ts
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 3 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

6/17/2026, 6:30:24 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack726/17/2026, 5:21:18 PM
stack72 linked parent of #6626/17/2026, 5:10:43 PM
Editable. Press Enter to edit.

stack72 commented 6/17/2026, 6:30:38 PM

Merged. Access bounded context landed — Grant and Group aggregates, shared value objects (Principal, Subject, ResourceSelector, Action, Effect, GrantSource), ownership validation tests. All 52 tests passing, no regressions.

Sign in to post a ripple.