DAT Structure & Scopes
Token Format (JWS)
Section titled “Token Format (JWS)”A Delegation Attestation Token is a JSON Web Signature (JWS) in Compact Serialization format (RFC 7515):
BASE64URL(Header) "." BASE64URL(Payload) "." BASE64URL(Signature)For hybrid signatures, a fourth segment carries the ML-DSA-65 signature:
BASE64URL(Header) "." BASE64URL(Payload) "." BASE64URL(Ed25519Sig) "." BASE64URL(MLDSA65Sig)This four-segment format is an IDProva extension to JWS. Implementations that do not support ML-DSA-65 MAY validate only the first three segments as standard JWS, but MUST note the reduced assurance level.
Header
Section titled “Header”{ "alg": "EdDSA", "typ": "idprova-dat+jwt", "kid": "did:idprova:example.com:pratyush#key-ed25519-1", "pqalg": "MLDSA65", "pqkid": "did:idprova:example.com:pratyush#key-mldsa65-1"}| Field | Required | Description |
|---|---|---|
alg | Yes | MUST be EdDSA for Ed25519 signatures. |
typ | Yes | MUST be idprova-dat+jwt. |
kid | Yes | DID URL of the signing key (Ed25519). |
pqalg | No | Post-quantum algorithm. MUST be MLDSA65 when present. |
pqkid | No | DID URL of the post-quantum signing key. |
Claims
Section titled “Claims”The DAT payload contains JWT-compatible claims:
{ "iss": "did:idprova:example.com:pratyush", "sub": "did:idprova:example.com:kai-lead-agent", "aud": "did:idprova:example.com:target-service", "iat": 1708732800, "exp": 1708819200, "nbf": 1708732800, "jti": "dat_01HQ3N8KXBC7YG2DMPVS5F6E9T", "scope": [ "mcp:tool:filesystem:read", "mcp:tool:filesystem:write", "mcp:resource:context:read", "idprova:agent:create" ], "constraints": { "maxCallsPerHour": 1000, "allowedIPs": ["10.0.0.0/8", "172.16.0.0/12"], "requiredTrustLevel": "L1", "maxDelegationDepth": 2, "geofence": ["AU", "NZ"] }, "configAttestation": "blake3:a1b2c3d4e5f67890...", "delegationChain": [ "dat_01HQ3M7JRAB6WF1CNKTS4E5D8S" ]}Claim Definitions
Section titled “Claim Definitions”| Claim | Type | Required | Description |
|---|---|---|---|
iss | DID string | Yes | The DID of the entity issuing (delegating) the token. |
sub | DID string | Yes | The DID of the entity receiving the delegation. |
aud | DID string | No | The intended verifier. When present, the verifier MUST check that its own DID matches. |
iat | NumericDate | Yes | Issued-at timestamp (seconds since Unix epoch). |
exp | NumericDate | Yes | Expiration timestamp. Max lifetime: 24 hours for L0–L1; 7 days for L2+. |
nbf | NumericDate | No | Not-before timestamp. Verifiers MUST reject the token before this time. |
jti | string | Yes | Unique token identifier. Format: dat_ + ULID or UUIDv7. |
scope | array | Yes | Array of scope strings defining permitted actions. |
constraints | object | No | Additional constraints on the delegation. |
configAttestation | string | No | Expected config hash of the subject agent. Mismatch → reject. |
delegationChain | array | No | Ordered jti values forming the chain from root principal. |
Scope Grammar
Section titled “Scope Grammar”Scopes define what actions a delegated agent is permitted to perform.
Formal Grammar
Section titled “Formal Grammar”scope = namespace ":" resource ":" actionnamespace = segmentresource = segment *( ":" segment )action = segment / wildcardsegment = 1*( ALPHA / DIGIT / "-" / "_" )wildcard = "*"Standard Namespaces
Section titled “Standard Namespaces”| Namespace | Description |
|---|---|
mcp | Model Context Protocol operations |
idprova | IDProva protocol operations |
a2a | Agent-to-Agent protocol operations |
http | HTTP endpoint access |
custom | User-defined operations |
Standard MCP Scopes
Section titled “Standard MCP Scopes”| Scope | Description |
|---|---|
mcp:tool:*:* | All tool operations |
mcp:tool:{name}:call | Call a specific tool |
mcp:tool:{name}:read | Read tool metadata |
mcp:resource:*:* | All resource operations |
mcp:resource:{name}:read | Read a specific resource |
mcp:resource:{name}:write | Write a specific resource |
mcp:prompt:*:* | All prompt operations |
mcp:prompt:{name}:use | Use a specific prompt |
Standard IDProva Scopes
Section titled “Standard IDProva Scopes”| Scope | Description |
|---|---|
idprova:agent:create | Create new agent identities |
idprova:agent:update | Update agent identity documents |
idprova:agent:deactivate | Deactivate agent identities |
idprova:delegation:issue | Issue new DATs |
idprova:delegation:revoke | Revoke existing DATs |
idprova:receipt:create | Create action receipts |
idprova:receipt:read | Read action receipts |
Wildcard Rules
Section titled “Wildcard Rules”*as the action component matches any action:mcp:tool:filesystem:*grants read, write, delete, etc.*as a resource segment matches any resource:mcp:tool:*:readgrants read on all tools.*:*:*grants all permissions. MUST only be issued by L3+ principals and SHOULD be avoided.
Scope Reduction Rule
Section titled “Scope Reduction Rule”When re-delegating, the child DAT’s scopes MUST be a subset of the parent DAT’s scopes. A delegatee MUST NOT escalate privileges.
Scope p covers scope s if:
pequalss, ORphas a wildcard that matches the corresponding segment ins.
Parent scope: mcp:tool:filesystem:*Child scope: mcp:tool:filesystem:read → VALID (covered by wildcard)Child scope: mcp:tool:database:read → INVALID (different resource)Constraints
Section titled “Constraints”The constraints object provides restrictions beyond scopes:
{ "constraints": { "maxCallsPerHour": 1000, "maxCallsPerDay": 10000, "maxConcurrent": 5, "allowedIPs": ["10.0.0.0/8"], "deniedIPs": ["10.0.0.1/32"], "requiredTrustLevel": "L1", "maxDelegationDepth": 2, "geofence": ["AU", "NZ", "US"], "timeWindows": [ { "days": ["Mon", "Tue", "Wed", "Thu", "Fri"], "startUTC": "00:00", "endUTC": "23:59" } ], "requiredConfigAttestation": true, "customConstraints": { "maxTokensPerRequest": 4096, "allowedModels": ["anthropic/claude-sonnet-4", "anthropic/claude-opus-4"] } }}Standard Constraint Fields
Section titled “Standard Constraint Fields”| Field | Type | Description |
|---|---|---|
maxCallsPerHour | integer | Maximum actions per clock hour. |
maxCallsPerDay | integer | Maximum actions per calendar day (UTC). |
maxConcurrent | integer | Maximum concurrent active operations. |
allowedIPs | string[] | CIDR ranges from which the agent may operate. |
deniedIPs | string[] | CIDR ranges explicitly blocked. Overrides allowedIPs. |
requiredTrustLevel | string | Minimum trust level the subject must maintain. |
maxDelegationDepth | integer | Maximum further delegation depth. 0 = no re-delegation. |
geofence | string[] | ISO 3166-1 alpha-2 country codes. |
timeWindows | object[] | Time windows during which the delegation is active. |
requiredConfigAttestation | boolean | If true, verifiers MUST check config attestation. |
customConstraints | object | Implementation-specific constraints. |
Constraint Inheritance
Section titled “Constraint Inheritance”When re-delegating, child constraints MUST be equal to or more restrictive than parent constraints:
- Numeric limits: child value ≤ parent value
- IP ranges: child set ⊆ parent set
- Trust level: child level ≥ parent level
- Delegation depth: child depth < parent depth
- Geofence: child set ⊆ parent set
- Time windows: child windows ⊆ parent windows
Delegation Chains
Section titled “Delegation Chains”Delegation chains trace the path of authority from a root principal to a leaf agent.
Root Principal (Human) └── DAT_1: delegates to Agent A └── DAT_2: Agent A delegates to Agent B └── DAT_3: Agent B delegates to Agent CThe delegationChain array in DAT_3 would be: ["dat_1_jti", "dat_2_jti"].
Chain Validation Algorithm
Section titled “Chain Validation Algorithm”ValidateChain(dat, resolver): 1. current = dat 2. chain = [current] 3. while current.delegationChain is not empty: a. parent_jti = current.delegationChain[last] b. parent_dat = resolver.resolveDAT(parent_jti) c. if parent_dat is null: return INVALID("broken chain") d. if parent_dat.sub != current.iss: return INVALID("chain mismatch") e. if parent_dat.exp < now(): return INVALID("parent expired") f. if not ValidateScopes(current.scope, parent_dat.scope): return INVALID("scope escalation") g. if not ValidateConstraints(current.constraints, parent_dat.constraints): return INVALID("constraint escalation") h. chain.prepend(parent_dat) i. current = parent_dat 4. root = chain[0] 5. root_did = resolver.resolveDID(root.iss) 6. if root_did is null: return INVALID("unknown root") 7. if root_did.deactivated: return INVALID("deactivated root") 8. return VALID(chain)Maximum Chain Depth: Default is 5. Restricted via maxDelegationDepth. Implementations MUST reject chains exceeding the maximum.
Revocation
Section titled “Revocation”DATs can be revoked before expiry through two mechanisms.
Revocation List
Section titled “Revocation List”The issuer publishes a revocation list at their DID’s service endpoint:
{ "issuer": "did:idprova:example.com:pratyush", "updated": "2026-02-24T12:00:00Z", "revocations": [ { "jti": "dat_01HQ3N8KXBC7YG2DMPVS5F6E9T", "revokedAt": "2026-02-24T11:30:00Z", "reason": "key-compromise" } ]}Revocation Reasons
Section titled “Revocation Reasons”| Reason | Description |
|---|---|
key-compromise | The signing key has been compromised. |
privilege-change | The agent’s permissions have changed. |
agent-deactivated | The subject agent has been deactivated. |
policy-violation | The agent violated its delegation policy. |
superseded | A new DAT has replaced this one. |
unspecified | No specific reason given. |
Inline Revocation Check
Section titled “Inline Revocation Check”For real-time revocation, verifiers query the issuer’s registry:
GET /v1/delegations/{jti}/status{ "jti": "dat_01HQ3N8KXBC7YG2DMPVS5F6E9T", "active": false, "revokedAt": "2026-02-24T11:30:00Z", "reason": "privilege-change"}Revocation Propagation
Section titled “Revocation Propagation”When a parent DAT in a chain is revoked, all child DATs in that chain are implicitly revoked. Verifiers MUST check the validity of the entire chain, not just the leaf DAT.
Next Steps
Section titled “Next Steps”- Action Receipts — Hash-chained audit records
- Protocol Bindings — How DATs are transmitted over MCP, A2A, HTTP
- Delegation (Concepts) — High-level delegation overview