Design
The consent model
Four primitives, one evaluation order, and a set of statements that sit outside both because nothing is allowed to negotiate with them.
The four primitives
| Primitive | Is | Is not |
|---|---|---|
| Subject | A person with an identifier, who can grant, narrow and withdraw | A role, a group, or a device that inherits someone else's consent |
| Scope | An atom of permission with a risk tier and an affirmation ceiling | A wildcard. There is no * grant, only a * deny |
| Window | A wall-clock ceiling on a grant, set at sign time and shrinkable later | Renewable in place. A new window is a new affirmation |
| Affirmation | A timestamped, factor-bound statement that a subject agreed, right then | Durable. Every scope has a max age after which it is simply gone |
Evaluation order
Every call resolves in this sequence and stops at the first match. The ordering is not configurable, is identical on every plan, and is the only part of the system we would call sacred.
1. hard limits platform denies, compiled in, overridable=false 2. explicit deny subject-declared limits, including mid-window 3. affirmation ceiling age(last_affirmation) > scope.max_age → deny 4. capacity gate sobriety, age, monitor presence → deny if unmet 5. capacity gate revoked-since check → deny if token predates withdrawal 6. explicit allow a signed grant covering action + subject + window 7. default deny always. silence has never resolved to allow
Affirmation factors
A factor is not stronger because it is inconvenient. The three we support are ordered by how well they survive an honest recount, which is the only property that matters here.
| Factor | Collected | Max age | Notes |
|---|---|---|---|
| written | Signed in the app or on paper, scanned | 90 days | Baseline for every policy. Not sufficient alone above medium risk |
| verbal | Spoken, captured as a local hash, never the audio | 60 minutes | Required for high and critical scopes. This is the safeword carrier |
| somatic | A check-in the subject performs on their own device | One window | Optional. The only factor that can be revoked without a network path |
Hard limits
Platform-level deny statements, compiled into the engine rather than stored as data, which is what makes them immune to the three classic bypasses: an admin console, a support override, and a database with a friendly DBA.
| Resource | Enforcement note |
|---|---|
| consent:ongoing | Consent is not a one-time grant and cannot be stored, prepaid, or inherited. |
| capacity:sober | A subject under the influence cannot be an affirming party. No exceptions, no waivers. |
| identity:forge | Misrepresenting who you are voids every policy signed under that identity, retroactively. |
| body:permanent | Anything irreversible is out of scope for every plan, forever, including Enterprise. |
| revocation:conditional | Revocation may never be made conditional, delayed, penalised, or require a reason. |
Because they live in code, they are auditable without trusting a running system: build the binary, read internal/policy/hard.go, run go test ./internal/policy -run Immutable. Enterprise deployments ship the reproducible-build attestation for exactly this reason.
Withdrawal
Withdrawal is the highest-precedent write in the system. It cannot be queued, batched, rate-limited, or made conditional on a counterparty accepting it, and it carries no reason field — not because reasons are bad, but because a schema that asks for one teaches people that some are insufficient.
invalidate all session tokens all regions, actor + counterparty clear every grant in the live set inherited=0, cached=0 freeze the policy object read-only, amendable only next window open the aftercare obligation non-deferrable, SLA-backed append 1 audit event actor, timestamp, breadth. nothing else
Roles
| Role | Posture | Eligible scopes | Holds the safeword |
|---|---|---|---|
| top | Holds scope — Directs the scene. Receives delegated authority for the duration of a window and returns it automatically at expiry. | 20 / 21 critical | yes |
| bottom | Grants scope — Delegates scope, not consent. Retains unilateral, unreasoned revocation for the entire session and after it. | 16 / 21 critical | yes |
| switch | Assumes scope — Role is per-partner and per-context. Policies never inherit across subjects — a grant as Top does not imply a grant as Bottom. | 21 / 21 critical | yes |
| monitor | Audits scope — Break-glass operator. Reads every session, may intervene, may never negotiate on someone else's behalf. | 10 / 21 low | yes |
| observer | Read-only — Presence without participation. Write scope is structurally absent from the role, not merely unassigned. | 3 / 21 low | yes |
| vanilla | No scope — The default onboarding state. Zero kink scopes, full audit visibility over your own record, and no expiry. | 4 / 21 low | yes |
Glossary
The vocabulary of this product was not invented by us. Where a term has a home outside enterprise security, that home is listed first, because the community that needed it got there decades earlier and with higher stakes.
| Term | Ordinary IAM meaning | Meaning here |
|---|---|---|
| safeword | Panic credential, duress code | A single string, held by every party, that revokes everything at once |
| hard limit | Non-negotiable compliance control | An out-of-scope resource, expressed as an immutable deny |
| soft limit | Advisory policy with an approval path | A limit that can be widened, but only after a cooling-off period |
| scene | Session / protected resource | One authorised window, with a beginning, a ceiling and a debrief |
| negotiation | Consent handshake / scope grant flow | A two-sided narrowing. Proposals grant nothing |
| check-in | Liveness probe / heartbeat | Ongoing authorisation. A missed one ends the window, silently |
| monitor | Break-glass operator | A third party with emergency write and zero negotiating authority |
| aftercare | Post-change support window | An obligation with an SLA, opened automatically by closure or withdrawal |
| drop | Revocation event | One party's decision, recorded as a fact and never as a debate |