DelegusDocsv0.3 rc1

Docs/Profile delegus-base-v3

Protocol

Profile delegus-base-v3

The checks Delegus runs on every request, in the order they run, for a relying party on the v0.3 profile. A profile is the published list of checks; every receipt pins it by its SHA-256 as protocol.profile_hash, so anyone holding a receipt knows exactly which rules decided it.

Release candidate. This describes v0.3-rc1, the current release candidate. New and existing relying parties are on it (profile delegus-base-v3). It is not frozen: the commitment construction is awaiting an external cryptography review, and the v0.2 specification stays the normative text until v0.3 is frozen. Details can still change.

Published at /profiles/delegus-base-v3. Until v0.3 is frozen, the document changes with each release-candidate edit and its hash moves with it; every receipt pins the exact bytes it was decided under, and the hash is fixed at the freeze.

What v3 adds#

New relying parties start on v3. A relying party registered earlier stays on delegus-base-v1, unchanged, until it moves.

Words used on this page:

Protocol checks#

Each check is true, false or "skipped". Protocol checks are designed to be reproducible by anyone given the Grant, Proof, Action, relying-party DID, a clock, the issuer's DID document snapshot, the status-list credential snapshot and, for budgeted Capabilities, the consumption snapshot. D2–D7 are reproducible by a party entitled to the dependency disclosure package; D5 is Delegus's attestation.

#CheckDENY reason
P1Grant parses and conforms to §3 (incl. parentGrant absent; budget well-typed)GRANT_MALFORMED / UNSUPPORTED_FEATURE
P2kid names a verification method present in the DID document snapshotISSUER_KEY_NOT_FOUND
P3Grant signature verifiesGRANT_SIGNATURE_INVALID
P4now ≥ validFromGRANT_NOT_YET_VALID
P5now < validUntilGRANT_EXPIRED
P6Status credential signed by Delegus Check; bit at statusListIndex is 0AUTHORITY_REVOKED
P7audience, if present, contains RPAUDIENCE_MISMATCH
P8Proof parses and conforms to §4 (incl. jti format)PROOF_MALFORMED
P9Proof signature verifies against Agent keyPROOF_SIGNATURE_INVALID
P10Proof iss == Grant subPROOF_AGENT_MISMATCH
P11Proof grant == Grant idPROOF_GRANT_MISMATCH
P12Proof aud == RP DIDPROOF_AUDIENCE_MISMATCH
P13iat within windowPROOF_EXPIRED
P14action_hash == hash of submitted ActionPROOF_ACTION_MISMATCH
P15Action valid for its type, including relies_on (1–8 entries, each exactly fingerprint and mode, no repeats); no unknown memberACTION_MALFORMED
P16Some Capability matches action.typeACTION_NOT_AUTHORIZED
P17All constraint keys knownUNKNOWN_CONSTRAINT
P18Currency authorizedCURRENCY_NOT_AUTHORIZED
P19amount ≤ maxAmountAMOUNT_EXCEEDS_AUTHORITY
P20resource matches a patternRESOURCE_NOT_AUTHORIZED
P21Some P20 survivor has budget headroom for the action (or declares no budget); period from validFrom in UTC, counts from the snapshotAUTHORITY_EXHAUSTED
D1Every requires entry appears in action.relies_on with the same fingerprint and the same modeDEPENDENCY_NOT_DECLARED
D2The fingerprint resolves, inside Delegus, to a receipt Delegus Check issued (recomputed from that receipt's bytes and its stored opening)DEPENDENCY_COMMITMENT_MISMATCH
D3That receipt's signature verifies against a Delegus Check receipt key and its body equals its payloadDEPENDENCY_RECEIPT_INVALID
D4Its decision is ALLOWDEPENDENCY_NOT_ALLOW
D5Every declared dependency belongs to one internal transactionDEPENDENCY_TRANSACTION_MISMATCH
D6CURRENT_AUTHORITY only: now < the dependency receipt's expires_atDEPENDENCY_AUTHORITY_EXPIRED
D7CURRENT_AUTHORITY only, three things about the earlier Grant, in this order: its Principal is in good standing (as T1 asks of the action's own Principal); the key that signed it is not marked compromised (as T3); and its revocation bit is 0 in its Principal's status-list credential (as P6). All read in the step before P6.DEPENDENCY_ISSUER_NOT_TRUSTED / DEPENDENCY_ISSUER_KEY_COMPROMISED / DEPENDENCY_AUTHORITY_REVOKED

P1–P20 are the v1 checks, with P15 applying the v0.3 Action rules and P16–P20 the v0.3 action types. In plain words, the new ones:

D1 runs once; D2–D7 run for each declared entry, in the order the action lists them. Each Dn is false if any entry fails it. An action with no relies_on, for a relying party that sends no requires, has D1–D7 true.

Trust checks: delegus-trust-v3#

Trust checks are Delegus's own attestation about the service state (who is registered, key status, replay, budgets). They are not reproducible offline by design.

#CheckDENY reason
T1issuer is a registered Principal in good standingISSUER_UNKNOWN (not registered) / ISSUER_NOT_TRUSTED (suspended or disputed)
T2Principal is domain-verifiedISSUER_UNVERIFIED
T3kid not marked compromisedISSUER_KEY_COMPROMISED
T5Replay: the Proof's jti has not been used at this relying party (an atomic write, run only after P1–P14 pass). Store unavailable → SERVICE_UNAVAILABLEPROOF_REPLAYED / SERVICE_UNAVAILABLE
T7The answer of the spend: the atomic decrement of the matched Capability's budget. consumed → true; exhausted (another request took the headroom first) → false; store unavailable → SERVICE_UNAVAILABLE. A Capability without budget makes T7 true without a writeAUTHORITY_EXHAUSTED / SERVICE_UNAVAILABLE

delegus-trust-v3 is T2, T3, T5, T1 strengthened with standing, and T7 (trust configuration trust_0003). delegus-trust-v2, the policy of a retired intermediate profile, was T1 as in v1, T2, T3, T5 and T7. T4 and T6 do not exist; identifiers are never reused.

Good standing. Delegus staff can suspend a company, or mark it disputed, on a misuse report, and lift that later, with a recorded reason. While a company is not in good standing, every request under its Grants gets a signed DENY with ISSUER_NOT_TRUSTED at T1. A company that is not registered at all still gets ISSUER_UNKNOWN. Receipts already signed never change. Standing is checked only for relying parties on delegus-base-v3; under delegus-base-v1, T1 is unchanged and ISSUER_NOT_TRUSTED stays reserved.

Spec §5.3 defines T1 this way: issuer is a registered Principal in good standing. Standing is Delegus trust data: staff mark a Principal suspended or disputed on a misuse report, with a reason, audited, and lift it the same way. Receipts already issued are never altered.

Evaluation order#

text
P1 → T1 → T2 → T3 → P2 → P3 → P4 → P5
   → [resolve declared dependencies; read revocation state, including each CURRENT_AUTHORITY dependency's]
   → P6 → P7 → P8 → … → P14
   → [atomic replay write]
   → T5 → P15 → … → P20
   → P21
   → D1 → (per relies_on entry) D2 → D3 → D4 → D5 → D6 → D7
   → [spend: atomic budget decrement, only if every check above is true]
   → T7

The bracketed steps are internal operations, not checks. The decision is DENY if any check is false, and reason is the first false check in this order. Dependency checks run after P21 so the agent's own reasons are reported first. The spend is last, so no request spends budget and is then refused.

What each check needs#

A check whose prerequisite did not pass is reported "skipped". P1–P20 and T1–T5 keep their v1 prerequisites (see DENY reason codes). v3 adds:

CheckNeeds
P21Every earlier check true: P1–P20 and T1, T2, T3, T5
D1–D7P21 true
D3 … D7, per entrythe previous D-check true for that entry
T7Every other check true

So a replayed, revoked, expired or wrongly addressed request never reads or spends budget, and never has its dependencies evaluated.

protocol.result differs from v1 when a trust check fails. Because P21 and D1–D7 wait on T1–T3 and T5, a v3 receipt refused by a trust check (for example PROOF_REPLAYED) shows those checks "skipped" and protocol.result: "FAIL", although no P-check is false. Under v1 the same replay shows protocol.result: "PASS". The decision and reason are the same. Read the reason from reason, never from protocol.result.

A dependency or budget refusal uses up the Proof. Both come after T5, so the agent needs a fresh Proof to try again.

Earlier version: delegus-base-v1 (v0.2)#

delegus-base-v1, with trust policy delegus-trust-v1 and receipt format delegus-receipt-v1, is the v0.2 profile. It stays published and frozen; delegus-base-v3 is the default. It is kept here for history and for every relying party that has not chosen v3; its receipts keep verifying under v0.2 rules.

delegus-base-v1 (v0.2)delegus-base-v3 (v0.3 rc1)
Protocol checksP1–P20P1–P21, D1–D7
Trust checksT1, T2, T3, T5 (delegus-trust-v1)T1 with standing, T2, T3, T5, T7 (delegus-trust-v3)
T1registered Principalregistered Principal in good standing
ISSUER_NOT_TRUSTEDreserved, never producedproduced at T1
Action typescommerce:purchase, api:calladds commerce:quote, commerce:accept, commerce:fulfil
budget constraintunknown key, P17 UNKNOWN_CONSTRAINTdefined; checked at P21, spent at T7
relies_on / requiresnot accepted (ACTION_MALFORMED / HTTP 400 REQUIREMENTS_NOT_SUPPORTED)accepted
Receiptdelegus-receipt-v1, matched Capability in plain textdelegus-receipt-v2, matched Capability pinned by commitment
Trust configurationtrust_0001trust_0003
Statusfrozen, publishedrelease candidate, published

The full v1 table is at /profiles/delegus-base-v1.

The receipt names the matched authority by authority_commitment (spec §5.6, §6.2, §6.3, §R.6).

History#

The profile document is pinned by hash in every receipt, so its bytes never change; a change is a new profile with a new name. The published delegus-base-v3, served at /profiles/delegus-base-v3, has this hash:

text
sha256:dffe1a6e71459fc55fb2469689a7c2da6bb2b5abbdcc0091906d8ac06cd374cd

On 25 Sep 2026 an interim build published one revision with a reworded sentence by mistake (the first hash below). It was reverted the same day. No production receipt pins it. It stays retrievable by hash at GET /evidence/{sha256}. Receipts from the development environment may pin it, or an earlier draft (the second):

text
sha256:c3fb3b6fb525aeca4988da10c1bdd045aaa9ae1c4eaa9f3076a0f309d4efa4be
sha256:fcd03a43febc57e3420c31856b8ef3ca3b4082e3eb0dda5253e2a28c3c613550