Delegated Authority Token — the principal-signed grant defining what an AI agent is allowed to do. Companion to sm-arp (ARP).
Project description
sm-dat — Delegated Authority Token
The portable, cryptographically signed grant a human gives an agent — what it's allowed to do, for how long, under what limits. Runtime-agnostic, vendor-neutral, MIT-licensed.
ARP records what an agent did. DAT records what an agent was allowed to do. Together they
answer the two halves of every accountability question — "did this happen?" (ARP) and
"was it authorized?" (DAT). DAT is the missing first half: ARP receipts ship today and
already carry an authority_chain field waiting for the grants that fill it.
A DAT is signed by the principal's key, not the agent's — so it is a non-repudiable statement by the human: "I permitted this, within these bounds."
from sm_arp import Identity, build_action
from sm_dat import (LedgerContext, StaticRevocationList, build_grant, sign_grant,
verify_grant, check_attenuation)
principal, agent = Identity.generate(), Identity.generate()
grant = sign_grant(principal, build_grant(
grantee_did=agent.did,
action_categories=["purchase"],
stateless={"amount_currency": "USD", "amount_cents_per_action_max": 5000,
"counterparty_allowlist": ["domain:amctheatres.com"]},
stateful={"amount_cents_per_period_max": 50000, "period": "month"},
not_before="2026-04-01T00:00:00Z",
not_after="2026-06-30T23:59:59Z",
revocation={"list_url": "https://principal.example/revocations.json"},
human_summary="Buy movie tickets, ≤$50/mo, AMC only.",
))
buy = build_action(category="purchase", human_summary="two tickets",
amount_cents=3000, currency="USD",
counterparty_label="domain:amctheatres.com")
ledger = LedgerContext.from_receipts([], grant["grant_id"]) # the agent's prior receipts
live = StaticRevocationList([], fetched_at="2026-04-10T19:00:00Z")
v = verify_grant(grant, buy, "2026-04-10T19:00:00Z", agent_did=agent.did,
ledger_context=ledger, revocation_checker=live)
print(v.status, v.reason) # SATISFIED / VIOLATED / INDETERMINATE
The full version of this — over-cap, the third outcome, an actual revocation, and a
delegation attenuation check — is examples/quickstart.py,
and it runs (real output, 2026-07-13):
in-bounds : SATISFIED ok
over cap : VIOLATED amount_cap_exceeded
no checker : INDETERMINATE revocation_unknown
revoked : VIOLATED revoked
attenuation : SATISFIED
(Two semantics worth noticing there: the revocation gate runs only for grants that
declare a revocation source — and once declared, verifying without a checker is
INDETERMINATE, never a silent pass. And a child grant that omits a cap its parent has
is a widening — check_attenuation rejects it.)
The one decision that defines this library
Authorization checks have three outcomes, not two: SATISFIED, VIOLATED, and
INDETERMINATE. A per-period budget cap ("≤$50/month") cannot be decided from one action alone —
the verifier must sum it against prior actions. If it lacks that ledger, sm-dat returns
INDETERMINATE(accounting_required) — it never silently passes a guarantee it could not
recompute. That "recompute, don't trust" discipline is inherited straight from sm-parc.
Demo
An interactive page recomputes the verdict in the browser (a faithful port of verify_grant) —
pick a scenario, watch the three-valued verdict and the decision trace update live. Try it at
demodat.stellarminds.ai. The three states:
In scope → SATISFIED
Over the per-action cap → VIOLATED(amount_cap_exceeded) — the real reason, not a bare "no":
A per-period budget with no ledger supplied → INDETERMINATE(accounting_required) — it
refuses to guess a budget it cannot compute:
Where it sits
| Question | Library |
|---|---|
| Who is this agent? | sm-arp / did:key |
| Did it happen, signed by the agent? | sm-arp |
| Was it permitted by the principal? | sm-dat |
| Is the agent trustworthy? | sm-parc |
| Approve this action, human-in-the-loop, now? | sm-oversight |
| What may the agent's plugins touch? | sm-airlock |
sm-oversight is synchronous per-action approval; sm-dat is standing autonomous
authorization granted ahead of time. sm-airlock is the agent's sandbox; sm-dat is the
principal's leash. No overlap.
Downstream, the dissociation-receipt suite consumes sm-dat as its authority leg:
sm-dissociation-receipt's
[arp] extra pins this package at an exact git SHA and wraps verify_authority_chain
behind its make_authority_adapter — "was this principal entitled to order a memory
exclusion?" is answered by a DAT grant.
Status
- WHITEPAPER.md — the motivation, design axioms, and what's novel: the
three-valued post-hoc recomputable verdict, receipt-anchored verification, and the
accounting_requiredbudget cap that refuses to guess. - SPEC.md — the normative draft: envelope, scope model, verification procedure, attenuation, revocation, verifier obligations, conformance corpus plan.
- Promoted from
sm-arp'sdat-companion.mdsketch. Targetsdat/0.1published parallel to ARP v0.2;dat/1.0and ARP v1.0 in lockstep.
Depends on sm-arp for identity, canonicalization, signatures, and the Agency Log — it never
re-implements crypto.
License
MIT © 2026 StellarMinds. See LICENSE.
Part of the NANDA ecosystem · built by StellarMinds.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sm_dat-0.2.0.tar.gz.
File metadata
- Download URL: sm_dat-0.2.0.tar.gz
- Upload date:
- Size: 753.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
840fb279d0e0592deecaedd5c1f1c042e0d70f92ca20a9ed1cf524e5cd2875d8
|
|
| MD5 |
9f3bda9af0d383275610611d146095b5
|
|
| BLAKE2b-256 |
4d7ba705aabc46713299ac411820a7f58829cfaa6f67fe134c9eea0942309dd0
|
Provenance
The following attestation bundles were made for sm_dat-0.2.0.tar.gz:
Publisher:
release.yml on Sharathvc23/sm-dat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sm_dat-0.2.0.tar.gz -
Subject digest:
840fb279d0e0592deecaedd5c1f1c042e0d70f92ca20a9ed1cf524e5cd2875d8 - Sigstore transparency entry: 2285559622
- Sigstore integration time:
-
Permalink:
Sharathvc23/sm-dat@c8668fcace18da1fa64f9f470ec88c0b5781789a -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Sharathvc23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8668fcace18da1fa64f9f470ec88c0b5781789a -
Trigger Event:
push
-
Statement type:
File details
Details for the file sm_dat-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sm_dat-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad082767c3566a68d7df79694fc2a7c550c5caad7c9542f7962e31869fd350f2
|
|
| MD5 |
d844ed1e52014ca7195f8df7e8ecdbb7
|
|
| BLAKE2b-256 |
6ac1616565de343c835f7de55c2d8d3f0f24fa97ba8a43235adfa5934a444bc3
|
Provenance
The following attestation bundles were made for sm_dat-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Sharathvc23/sm-dat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sm_dat-0.2.0-py3-none-any.whl -
Subject digest:
ad082767c3566a68d7df79694fc2a7c550c5caad7c9542f7962e31869fd350f2 - Sigstore transparency entry: 2285559681
- Sigstore integration time:
-
Permalink:
Sharathvc23/sm-dat@c8668fcace18da1fa64f9f470ec88c0b5781789a -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Sharathvc23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8668fcace18da1fa64f9f470ec88c0b5781789a -
Trigger Event:
push
-
Statement type: