Claim → Denial Mapping¶
A claim is the unit of operational entitlement; a denial is what the runtime returns when a governed action cannot proceed. This doc maps each seed claim to the denial classes it can produce, and explains why — a claim’s denial class is determined by which governance layer gates it, not by the claim ID itself.
Where a denial class comes from¶
A governed action flows through the decision-precedence pipeline (policy → entitlement → override). Each layer, plus the universal runtime-state checks, emits a specific denial class:
Source |
Condition |
Denial class |
|---|---|---|
Entitlement |
Claim missing or exhausted and a commerce path exists |
|
Entitlement |
Claim missing or exhausted and no commerce path exists |
|
Policy |
A policy rule denies, the author marked it overrideable, no grant covers the scope |
|
Policy |
A policy rule denies an inherently disallowed action (not overrideable) |
|
Universal state |
Policy / entitlement / override is past TTL with no fresh substitute |
|
Universal state |
Transient condition (evaluator unavailable, ledger lock, OCI fetch in flight) |
|
So a claim’s possible denial classes are the union of what its gating layers can
emit, plus the two universal classes (DENY_RETRYABLE, DENY_STALE_STATE) that
apply to every claim.
Governance modes¶
Every seed claim is governed in one of three modes in a given deployment. The mode is deployment-configured (by the policy bundle and the entitlement bundle), not an intrinsic property of the claim — the table below shows the MVP-A / roadmap intent.
Entitlement-metered — the claim is a metered capability drawn from an entitlement bundle. Exhaustion/absence yields
DENY_PURCHASABLE(orDENY_FINALwith no commerce path).Policy-restricted — a policy rule gates the claim (e.g. a geofence). A denied, author-overrideable rule yields
DENY_OVERRIDEABLE(orDENY_FINAL).Baseline — permitted by default; only the universal state classes can deny it.
Per-claim mapping¶
Claim |
MVP-A status |
Governance mode |
Possible denial classes |
|---|---|---|---|
|
post-MVP-A |
entitlement-metered |
|
|
post-MVP-A |
entitlement-metered |
|
|
demo-active |
baseline |
universal only |
|
demo-active (Scene 1) |
entitlement-metered |
|
|
demo-active (Scene 2) |
policy-restricted |
|
|
reserved |
policy-restricted |
|
|
reserved |
policy-restricted |
|
|
reserved |
baseline |
universal only |
|
reserved |
baseline |
universal only |
|
reserved |
entitlement-metered |
|
|
reserved |
entitlement-metered |
|
|
reserved |
entitlement-metered |
|
“+ universal” = DENY_RETRYABLE and DENY_STALE_STATE, which any claim can produce
from a transient or stale-state condition regardless of mode. A baseline claim is
never denied by the policy or entitlement layers, so only the universal classes
apply.
The two demo scenes¶
Scene 1 — entitlement exhaustion. The operator commands a metered nav capability (
robot.nav.dynamic_reroute, “explore beyond the mapped area”). The entitlement is used up, so the runtime returnsDENY_PURCHASABLE(purchase_available: true); a mock top-up mints a fresh bundle and the retry runs. Recovery is purchase only — an override never satisfies an entitlement.Scene 2 — restricted zone. The operator commands a route into a restricted zone (
robot.nav.restricted_zone_entry). A policy rule denies it as overrideable, so the runtime returnsDENY_OVERRIDEABLE(override_available: true); a locally signed override grant permits the retry. Recovery is override only — a purchase does not unblock a policy restriction.
These are the two recovery paths made visible, and they are non-fungible: the denial class names the single legitimate path (see Denial Contract).