@agenticprimitives/delegation 1.0.0-alpha.25 → 1.0.0-alpha.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { ROOT_AUTHORITY } from './types.js';
2
- import { buildCaveat, encodeTimestampTerms, encodeValueTerms } from './caveats.js';
2
+ import { buildCaveat, buildSessionAudienceCaveat, encodeTimestampTerms, encodeValueTerms } from './caveats.js';
3
3
  import { hashDelegation } from './hash.js';
4
4
  function randomSalt() {
5
5
  const b = new Uint8Array(16);
@@ -11,7 +11,7 @@ function randomSalt() {
11
11
  }
12
12
  /**
13
13
  * Build the session-delegation leaf `delegator (principal SA) → sessionKey`, with a timestamp (TTL) +
14
- * value-0 caveat, UNSIGNED. Returns `{ leaf, digest }`; the caller signs `digest` with the member's live
14
+ * value-0 + session-audience caveat (spec 408 §2.1), UNSIGNED. Returns `{ leaf, digest }`; the caller signs `digest` with the member's live
15
15
  * credential and sets `leaf.signature`. v4 binds to the DELEGATOR (the principal's canonical identity), so
16
16
  * the same credential that signs the `member→relying` delegation at connect also authorizes the session key.
17
17
  */
@@ -23,6 +23,7 @@ export function buildSessionDelegation(p) {
23
23
  caveats: [
24
24
  buildCaveat(p.enforcers.timestamp, encodeTimestampTerms(0, p.validUntil)),
25
25
  buildCaveat(p.enforcers.value, encodeValueTerms(0n)),
26
+ buildSessionAudienceCaveat(p.presentsTo),
26
27
  ],
27
28
  salt: p.salt ?? randomSalt(),
28
29
  signature: '0x',
@@ -1 +1 @@
1
- {"version":3,"file":"session-delegation.js","sourceRoot":"","sources":["../src/session-delegation.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAiB3C,SAAS,UAAU;IACjB,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7B,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,MAAM,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,CAA0B;IAC/D,MAAM,IAAI,GAAe;QACvB,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,QAAQ,EAAE,CAAC,CAAC,iBAAiB;QAC7B,SAAS,EAAE,cAAc;QACzB,OAAO,EAAE;YACP,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YACzE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,CAAC;SACrD;QACD,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,UAAU,EAAE;QAC5B,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC;AAChF,CAAC"}
1
+ {"version":3,"file":"session-delegation.js","sourceRoot":"","sources":["../src/session-delegation.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAqB3C,SAAS,UAAU;IACjB,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7B,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,MAAM,CAAC,IAAI,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,CAA0B;IAC/D,MAAM,IAAI,GAAe;QACvB,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,QAAQ,EAAE,CAAC,CAAC,iBAAiB;QAC7B,SAAS,EAAE,cAAc;QACzB,OAAO,EAAE;YACP,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;YACzE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACpD,0BAA0B,CAAC,CAAC,CAAC,UAAU,CAAC;SACzC;QACD,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,UAAU,EAAE;QAC5B,SAAS,EAAE,IAAI;KAChB,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,CAAC;AAChF,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { type Address, type Hex } from 'viem';
2
+ import { type Delegation } from './types.js';
3
+ import { type EnforcerAddresses, type MandateRequirementV1, type SubsetHandlers } from './mandate.js';
4
+ /** The wire as it travels (salt as a decimal string), beside what it allows and where it is hashed. */
5
+ export interface StandingWireV1 {
6
+ v: 1;
7
+ /** The template that minted it (`act-as-me`), for the surface that lists it. */
8
+ template: string;
9
+ /** The ONE capability it covers. */
10
+ capability: string;
11
+ /** The standing delegation: principal → delegate key. Wire-shaped. */
12
+ wire: Record<string, unknown>;
13
+ /** Its EIP-712 digest on `chainId` / `delegationManager`. */
14
+ ref: Hex;
15
+ /** What it allows, as the capability's handler reads it — the parent requirement a child is bounded by. */
16
+ requirement: Omit<MandateRequirementV1, 'intentDigest'>;
17
+ enforcers: EnforcerAddresses;
18
+ chainId: number;
19
+ delegationManager: Address;
20
+ grantedAt: string;
21
+ }
22
+ export interface BuildStandingWireInput {
23
+ template: string;
24
+ /** The principal whose authority this is: the person (a capability), or her TREASURY (a payment — assets live only in treasuries). */
25
+ delegator: Address;
26
+ /** The delegate KEY (a Worker's custody key, a runtime's key) — never the person, never a session. */
27
+ delegate: Address;
28
+ capability: string;
29
+ /** A payment's bounds. Required for `treasury.payment.execute`; refused for anything else. */
30
+ payment?: {
31
+ payee: Address;
32
+ asset: Address;
33
+ maxAmount: bigint;
34
+ maxAggregate?: bigint;
35
+ maxRedemptionsPerWindow?: number;
36
+ windowSeconds?: number;
37
+ };
38
+ validForSeconds: number;
39
+ enforcers: EnforcerAddresses;
40
+ chainId: number;
41
+ delegationManager: Address;
42
+ /** Random 128-bit salt; injected so a test can be deterministic. */
43
+ salt?: bigint;
44
+ handlers?: SubsetHandlers;
45
+ }
46
+ /** The RAR type a capability is bounded by — the verifier's own map. */
47
+ export declare const standingRequirementType: (capability: string) => string;
48
+ /**
49
+ * The UNSIGNED standing wire and its digest. The caller signs `ref` with the delegator's custodian (an off-chain
50
+ * signature, or the approved-digest sentinel after a batch approval) and sets `wire.signature`.
51
+ */
52
+ export declare function buildStandingWire(i: BuildStandingWireInput): {
53
+ standing: StandingWireV1;
54
+ delegation: Delegation;
55
+ };
56
+ /** Attach the signature the custodian produced over `ref` (or the approved-digest sentinel). */
57
+ export declare function signedStandingWire(s: StandingWireV1, signature: Hex): StandingWireV1;
58
+ /** What a parked run said it needs — the `authority_required` reply's three fields. */
59
+ export interface ParkedNeedV1 {
60
+ requirement: MandateRequirementV1;
61
+ delegator: Address;
62
+ delegate: Address;
63
+ }
64
+ export declare function parkedNeedOf(data: unknown): ParkedNeedV1 | null;
65
+ /** Does this standing wire cover the capability a step needs? Type and capability, not yet the bounds. */
66
+ export declare function standingCovers(s: StandingWireV1, capabilityId: string): boolean;
67
+ /** Pick the standing wire for a parked need: the one whose capability matches AND whose principal is the need's delegator. */
68
+ export declare function standingFor(set: readonly StandingWireV1[], need: ParkedNeedV1, capabilityId: string): StandingWireV1 | null;
69
+ export type DerivedChain = {
70
+ ok: true;
71
+ presented: Array<Record<string, unknown>>;
72
+ childRef: Hex;
73
+ parentRef: Hex;
74
+ } | {
75
+ ok: false;
76
+ reason: string;
77
+ };
78
+ /**
79
+ * The child for THIS intent, from the standing wire, signed with the delegate key — or why not. The need must be an
80
+ * act OF the wire's principal and ⊆ the wire (the capability's handler judges: for a payment, the amount against
81
+ * the cap, the payee and the asset against the wire's); its window is clamped into the wire's. Anything else stays
82
+ * parked for the person — the surface's `grant_link` still works.
83
+ */
84
+ export declare function deriveFromStanding(s: StandingWireV1, need: ParkedNeedV1, sign: (digest: Hex) => Promise<Hex>, handlers?: SubsetHandlers): Promise<DerivedChain>;
85
+ /** Is this wire STANDING — no intent binding among its caveats? (A mandate always carries one.) */
86
+ export declare function isStandingWire(wire: {
87
+ caveats?: ReadonlyArray<{
88
+ enforcer: string;
89
+ terms: string;
90
+ args?: string;
91
+ }>;
92
+ }, digestBindingEnforcer: Address): boolean;
93
+ //# sourceMappingURL=standing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standing.d.ts","sourceRoot":"","sources":["../src/standing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ // STANDING WIRES — one capability, decided once (spec 397 `act-as-me`; the shape spec 400 W2a opened for a runtime's
2
+ // standing grant). A standing wire is a delegation from a principal (a person, or her treasury for a payment) to a
3
+ // DELEGATE KEY, caveated to ONE capability selector and a window — and, for a payment, to one payee, one asset and
4
+ // a cap — with NO intent binding. That absence is what makes it standing: it is a capability, not a mandate
5
+ // (`verifyMandateForStep` refuses it alone, `not-a-mandate`), and nothing acts on it directly.
6
+ //
7
+ // When a run parks `authority_required`, the holder of the delegate key DERIVES the mandate the run asked for: a
8
+ // child of the standing wire bound to exactly that intent (`deriveMandate`, subset-checked by the capability's own
9
+ // handler), signs it with the delegate key, and presents the chain [child, standing]. The harness verifies every
10
+ // link — the standing wire's signature against the principal (ERC-1271 / approved digest), its revocation on chain,
11
+ // the child ⊆ parent, the intent and plan binding — before the step acts. Revoke the standing wire on chain and the
12
+ // next derivation is refused everywhere.
13
+ //
14
+ // What a standing wire is NOT: a session, a bearer, a wildcard (never `A2A_ANY_SKILL`), or a pre-approval of
15
+ // anything but the named capability within the window and the cap. One wire, one capability selector.
16
+ import { toHex } from 'viem';
17
+ import { ROOT_AUTHORITY } from './types.js';
18
+ import { hashDelegation } from './hash.js';
19
+ import { readDigestBindings } from './caveats.js';
20
+ import { deriveMandate, subsetHandlerFor } from './mandate.js';
21
+ import { CAPABILITY_RAR_TYPE, DEFAULT_SUBSET_HANDLERS, PAYMENT_RAR_TYPE } from './mandate-handlers.js';
22
+ /** The RAR type a capability is bounded by — the verifier's own map. */
23
+ export const standingRequirementType = (capability) => (capability === 'treasury.payment.execute' ? PAYMENT_RAR_TYPE : CAPABILITY_RAR_TYPE);
24
+ /**
25
+ * The UNSIGNED standing wire and its digest. The caller signs `ref` with the delegator's custodian (an off-chain
26
+ * signature, or the approved-digest sentinel after a batch approval) and sets `wire.signature`.
27
+ */
28
+ export function buildStandingWire(i) {
29
+ if (!i.capability.trim())
30
+ throw new Error('a standing wire names one capability');
31
+ const type = standingRequirementType(i.capability);
32
+ if (type === PAYMENT_RAR_TYPE && !i.payment)
33
+ throw new Error('a standing payment wire needs its bounds: payee, asset, maxAmount');
34
+ if (type !== PAYMENT_RAR_TYPE && i.payment)
35
+ throw new Error(`${i.capability} is not a payment — it takes no cap`);
36
+ if (i.payment && i.payment.maxAmount <= 0n)
37
+ throw new Error('the cap must be above zero');
38
+ const h = subsetHandlerFor(type, i.handlers ?? DEFAULT_SUBSET_HANDLERS);
39
+ if (!h)
40
+ throw new Error(`no subset handler for ${type}`);
41
+ const now = Math.floor(Date.now() / 1000);
42
+ const requirement = {
43
+ type,
44
+ // A payment need arrives from the harness with `actions: [capability]` and `locations: [asset]` (the step's
45
+ // shape), and from a read-back wire as `actions: ['execute']` (the handler's shape). The parent names both, so
46
+ // `isSubset` holds for either child; the on-chain selectors are the handler's and do not depend on this list.
47
+ actions: type === PAYMENT_RAR_TYPE ? ['execute', i.capability] : [i.capability],
48
+ validAfter: now - 60,
49
+ validUntil: now + i.validForSeconds,
50
+ ...(i.payment ? { locations: [i.payment.asset.toLowerCase()], limits: {
51
+ payee: i.payment.payee.toLowerCase(), asset: i.payment.asset.toLowerCase(),
52
+ maxAmount: i.payment.maxAmount.toString(), maxAggregate: (i.payment.maxAggregate ?? i.payment.maxAmount).toString(),
53
+ maxRedemptionsPerWindow: i.payment.maxRedemptionsPerWindow ?? 1, windowSeconds: i.payment.windowSeconds ?? 86_400,
54
+ } } : {}),
55
+ };
56
+ const caveats = h.toCaveats(requirement, i.enforcers);
57
+ const salt = i.salt ?? BigInt(toHex(crypto.getRandomValues(new Uint8Array(16))));
58
+ const delegation = { delegator: i.delegator, delegate: i.delegate, authority: ROOT_AUTHORITY, caveats, salt, signature: '0x' };
59
+ const ref = hashDelegation(delegation, i.chainId, i.delegationManager);
60
+ return {
61
+ delegation,
62
+ standing: { v: 1, template: i.template, capability: i.capability, wire: { ...delegation, salt: salt.toString() }, ref, requirement, enforcers: i.enforcers, chainId: i.chainId, delegationManager: i.delegationManager, grantedAt: new Date().toISOString() },
63
+ };
64
+ }
65
+ /** Attach the signature the custodian produced over `ref` (or the approved-digest sentinel). */
66
+ export function signedStandingWire(s, signature) {
67
+ return { ...s, wire: { ...s.wire, signature } };
68
+ }
69
+ export function parkedNeedOf(data) {
70
+ const d = data;
71
+ if (!d?.requirement || typeof d.requirement !== 'object' || !d.delegator || !d.delegate)
72
+ return null;
73
+ if (typeof d.requirement.intentDigest !== 'string' || !Array.isArray(d.requirement.actions))
74
+ return null;
75
+ return { requirement: d.requirement, delegator: d.delegator, delegate: d.delegate };
76
+ }
77
+ /** Does this standing wire cover the capability a step needs? Type and capability, not yet the bounds. */
78
+ export function standingCovers(s, capabilityId) {
79
+ return s.capability === capabilityId && s.requirement.type === standingRequirementType(capabilityId);
80
+ }
81
+ /** Pick the standing wire for a parked need: the one whose capability matches AND whose principal is the need's delegator. */
82
+ export function standingFor(set, need, capabilityId) {
83
+ const want = need.delegator.toLowerCase();
84
+ return set.find((s) => standingCovers(s, capabilityId) && String(s.wire.delegator ?? '').toLowerCase() === want && s.requirement.type === need.requirement.type) ?? null;
85
+ }
86
+ /**
87
+ * The child for THIS intent, from the standing wire, signed with the delegate key — or why not. The need must be an
88
+ * act OF the wire's principal and ⊆ the wire (the capability's handler judges: for a payment, the amount against
89
+ * the cap, the payee and the asset against the wire's); its window is clamped into the wire's. Anything else stays
90
+ * parked for the person — the surface's `grant_link` still works.
91
+ */
92
+ export async function deriveFromStanding(s, need, sign, handlers = DEFAULT_SUBSET_HANDLERS) {
93
+ if (String(s.wire.delegator ?? '').toLowerCase() !== need.delegator.toLowerCase())
94
+ return { ok: false, reason: `the run needs an act of ${need.delegator}; this wire is ${String(s.wire.delegator)}'s` };
95
+ if (need.requirement.type !== s.requirement.type)
96
+ return { ok: false, reason: `the run needs a ${need.requirement.type} mandate; this wire is ${s.requirement.type}` };
97
+ const parent = { ...s.wire, salt: BigInt(String(s.wire.salt)) };
98
+ const now = Math.floor(Date.now() / 1000);
99
+ const validAfter = Math.max(need.requirement.validAfter ?? 0, s.requirement.validAfter ?? 0);
100
+ const validUntil = Math.min(need.requirement.validUntil, s.requirement.validUntil);
101
+ if (validAfter > now || validUntil <= now)
102
+ return { ok: false, reason: `the standing wire's window (until ${new Date(s.requirement.validUntil * 1000).toISOString().slice(0, 16)}) does not cover now` };
103
+ const salt = BigInt(toHex(crypto.getRandomValues(new Uint8Array(16))));
104
+ const out = deriveMandate({
105
+ parent,
106
+ parentRequirement: { ...s.requirement, intentDigest: need.requirement.intentDigest },
107
+ requirement: { ...need.requirement, validAfter, validUntil },
108
+ grantee: need.delegate,
109
+ enforcers: s.enforcers, chainId: s.chainId, delegationManager: s.delegationManager, salt, handlers,
110
+ });
111
+ if (!out.ok)
112
+ return { ok: false, reason: out.reason };
113
+ const signature = await sign(out.digest);
114
+ const child = { ...out.delegation, signature, salt: salt.toString() };
115
+ return { ok: true, presented: [child, s.wire], childRef: out.digest, parentRef: s.ref };
116
+ }
117
+ /** Is this wire STANDING — no intent binding among its caveats? (A mandate always carries one.) */
118
+ export function isStandingWire(wire, digestBindingEnforcer) {
119
+ const caveats = (wire.caveats ?? []).map((c) => ({ enforcer: c.enforcer, terms: c.terms, args: (c.args ?? '0x') }));
120
+ return !readDigestBindings(caveats, digestBindingEnforcer).intent;
121
+ }
122
+ //# sourceMappingURL=standing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standing.js","sourceRoot":"","sources":["../src/standing.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"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"}
package/dist/token.js CHANGED
@@ -16,7 +16,7 @@ import { keccak_256 } from '@noble/hashes/sha3.js';
16
16
  import { createPublicClient, http } from 'viem';
17
17
  import { hashDelegation } from './hash.js';
18
18
  import { evaluateCaveats } from './evaluator.js';
19
- import { DATA_SCOPE_ENFORCER, decodeDataScopeTerms, VAULT_RECORD_SCOPE_ENFORCER, decodeVaultRecordScopeTerms } from './caveats.js';
19
+ import { DATA_SCOPE_ENFORCER, decodeDataScopeTerms, VAULT_RECORD_SCOPE_ENFORCER, decodeVaultRecordScopeTerms, readSessionAudience } from './caveats.js';
20
20
  import { verifyUniversalSignature } from './onchain.js';
21
21
  import { verifyOffChainQuorum } from './quorum.js';
22
22
  import { buildEvent } from '@agenticprimitives/audit';
@@ -323,6 +323,15 @@ export function sessionDelegateBindingError(delegation, sessionDelegation, sessi
323
323
  if (sessionDelegation.delegate.toLowerCase() !== sessionKeyAddress.toLowerCase()) {
324
324
  return 'session key is not the session-delegation delegate (DEL-001)';
325
325
  }
326
+ // Spec 408 §2.1 (R917-P-2) — THE ROOT'S DELEGATE IS BOUND. The leaf names the delegates this session key
327
+ // may present the principal's delegations to; a delegation to anyone else is refused, however valid it
328
+ // is on its own. A leaf that names nobody is refused outright: no knob re-admits the old shape.
329
+ const audience = readSessionAudience(sessionDelegation.caveats);
330
+ if (!audience)
331
+ return 'session-delegation names no audience — a leaf must say which delegates it may present to (spec 408 §2.1)';
332
+ if (!audience.includes(delegation.delegate.toLowerCase())) {
333
+ return `session-delegation does not admit presenting to ${delegation.delegate} — the leaf was issued for other delegates (spec 408 §2.1)`;
334
+ }
326
335
  return null;
327
336
  }
328
337
  /**
@@ -477,66 +486,46 @@ export async function verifyDelegationToken(token, opts) {
477
486
  : null;
478
487
  }
479
488
  };
480
- {
481
- // Root delegation revocation (unchanged semantics).
482
- const rootReason = await revocationRejection(eip712Hash);
483
- if (rootReason)
484
- return rejectWith(rootReason, claims.delegation.delegator, eip712Hash);
485
- // DEL-002: the session-delegation LEAF (DEL-001 session-key binding) is separately revocable on-chain
486
- // (revokeDelegation(leafHash)), but was NEVER checked — so revoking the session-key binding did not
487
- // invalidate the token until the ROOT was also revoked. Check the leaf with the SAME fail-closed model
488
- // so a revoked (e.g. compromised) session key is rejected as tightly as a revoked root.
489
- if (claims.sessionDelegation) {
490
- const leafHash = hashDelegation(claims.sessionDelegation, opts.chainId, opts.delegationManager);
491
- const leafReason = await revocationRejection(leafHash);
492
- if (leafReason)
493
- return rejectWith(`session-delegation leaf: ${leafReason}`, claims.delegation.delegator, leafHash);
489
+ // THE ROOT'S SIGNATURE — one of three surfaces, the same policy. Returns a rejection reason or null.
490
+ const rootSignatureRejection = async () => {
491
+ if (opts.chainSignatureReader) {
492
+ // spec 289 §5 (W3) — main delegator signature through the resilient port.
493
+ return validateSaSigViaReader(claims.delegation.delegator, eip712Hash, claims.delegation.signature);
494
494
  }
495
- }
496
- if (opts.chainSignatureReader) {
497
- // spec 289 §5 (W3) — main delegator signature through the resilient port.
498
- const reason = await validateSaSigViaReader(claims.delegation.delegator, eip712Hash, claims.delegation.signature);
499
- if (reason)
500
- return rejectWith(reason, claims.delegation.delegator, eip712Hash);
501
- }
502
- else if (validateSaSig) {
503
- // spec 270 v4 — one connection-agnostic surface; counterfactual delegators verify via ERC-6492, so
504
- // no requireDeployed hard-reject.
505
- try {
506
- if (!(await validateSaSig(claims.delegation.delegator, eip712Hash, claims.delegation.signature))) {
507
- return rejectWith('signature validation failed', claims.delegation.delegator, eip712Hash);
495
+ if (validateSaSig) {
496
+ // spec 270 v4 — one connection-agnostic surface; counterfactual delegators verify via ERC-6492, so
497
+ // no requireDeployed hard-reject.
498
+ try {
499
+ if (!(await validateSaSig(claims.delegation.delegator, eip712Hash, claims.delegation.signature))) {
500
+ return 'signature validation failed';
501
+ }
502
+ return null;
503
+ }
504
+ catch (e) {
505
+ return `signature validation reverted: ${e instanceof Error ? e.message : e}`;
508
506
  }
509
507
  }
510
- catch (e) {
511
- return rejectWith(`signature validation reverted: ${e instanceof Error ? e.message : e}`, claims.delegation.delegator, eip712Hash);
512
- }
513
- }
514
- else {
515
508
  try {
516
509
  const code = await publicClient.getCode({ address: claims.delegation.delegator });
517
510
  const isDeployed = !!(code && code !== '0x' && code.length > 2);
518
511
  if (!isDeployed) {
519
512
  if (requireDeployed) {
520
- return rejectWith(`delegator smart account ${claims.delegation.delegator} is not deployed — cannot verify ERC-1271. Set verifyDelegationToken opt requireDeployed=false only for explicit counterfactual-demo use cases.`, claims.delegation.delegator, eip712Hash);
521
- }
522
- // Tolerated: caller opted into the undeployed path explicitly.
523
- }
524
- else {
525
- const magic = (await publicClient.readContract({
526
- address: claims.delegation.delegator,
527
- abi: ACCOUNT_ABI_ERC1271,
528
- functionName: 'isValidSignature',
529
- args: [eip712Hash, claims.delegation.signature],
530
- }));
531
- if (magic.toLowerCase() !== ERC1271_MAGIC) {
532
- return rejectWith('erc1271 validation failed', claims.delegation.delegator, eip712Hash);
513
+ return `delegator smart account ${claims.delegation.delegator} is not deployed — cannot verify ERC-1271. Set verifyDelegationToken opt requireDeployed=false only for explicit counterfactual-demo use cases.`;
533
514
  }
515
+ return null; // Tolerated: caller opted into the undeployed path explicitly.
534
516
  }
517
+ const magic = (await publicClient.readContract({
518
+ address: claims.delegation.delegator,
519
+ abi: ACCOUNT_ABI_ERC1271,
520
+ functionName: 'isValidSignature',
521
+ args: [eip712Hash, claims.delegation.signature],
522
+ }));
523
+ return magic.toLowerCase() !== ERC1271_MAGIC ? 'erc1271 validation failed' : null;
535
524
  }
536
525
  catch (e) {
537
- return rejectWith(`erc1271 call reverted: ${e instanceof Error ? e.message : e}`, claims.delegation.delegator, eip712Hash);
526
+ return `erc1271 call reverted: ${e instanceof Error ? e.message : e}`;
538
527
  }
539
- }
528
+ };
540
529
  // 3.5. DEL-001 (spec 270 v4) — session-key↔identity binding.
541
530
  //
542
531
  // The full signed `delegation` travels in cleartext inside every token, so a verifier that only
@@ -548,51 +537,78 @@ export async function verifyDelegationToken(token, opts) {
548
537
  // an attacker can't forge the SA's authorization of THEIR key. `principal` stays `delegation.delegator`.
549
538
  // DEL-001 (ADR-0036): binding is ENFORCED BY DEFAULT — fail-closed. Only an explicit
550
539
  // `allowUnboundSessionToken: true` (legacy / non-client-minted path) skips it.
551
- if (!opts.allowUnboundSessionToken) {
552
- // Chain-free checks: leaf present, delegator-link, delegate === presenting session key.
553
- const bindErr = sessionDelegateBindingError(claims.delegation, claims.sessionDelegation, recovered);
554
- if (bindErr)
555
- return rejectWith(bindErr, claims.delegation.delegator, eip712Hash);
556
- const sd = claims.sessionDelegation;
557
- // The delegator SA (the principal's canonical identity) actually authorized THIS session key. Validated
558
- // via the UniversalSignatureValidator when configured (v4 — connection-agnostic: every credential
559
- // strategy passes through one surface), else legacy deployed-ERC-1271.
560
- const sdHash = hashDelegation(sd, opts.chainId, opts.delegationManager);
540
+ //
541
+ // The chain-free binding checks (leaf present, delegator-link, delegate === presenting session key) are
542
+ // computed now and JUDGED after the root signature, where they always were; a leaf that fails them has
543
+ // no signature worth reading.
544
+ const bindErr = !opts.allowUnboundSessionToken ? sessionDelegateBindingError(claims.delegation, claims.sessionDelegation, recovered) : null;
545
+ const sd = !opts.allowUnboundSessionToken && !bindErr ? claims.sessionDelegation : null;
546
+ const sdHash = sd ? hashDelegation(sd, opts.chainId, opts.delegationManager) : null;
547
+ // The leaf's signature — the delegator SA (the principal's canonical identity) actually authorized THIS
548
+ // session key. Validated via the UniversalSignatureValidator when configured (v4 — connection-agnostic:
549
+ // every credential strategy passes through one surface), else legacy deployed-ERC-1271.
550
+ const leafSignatureRejection = async () => {
551
+ if (!sd || !sdHash)
552
+ return null;
561
553
  try {
562
554
  if (opts.chainSignatureReader) {
563
555
  // spec 289 §5 (W3) — DEL-001 leaf signature through the resilient port.
564
556
  const reason = await validateSaSigViaReader(sd.delegator, sdHash, sd.signature);
565
- if (reason)
566
- return rejectWith(`session-delegation ${reason} (DEL-001)`, claims.delegation.delegator, eip712Hash);
557
+ return reason ? `session-delegation ${reason} (DEL-001)` : null;
567
558
  }
568
- else if (validateSaSig) {
569
- if (!(await validateSaSig(sd.delegator, sdHash, sd.signature))) {
570
- return rejectWith('session-delegation signature validation failed (DEL-001)', claims.delegation.delegator, eip712Hash);
571
- }
559
+ if (validateSaSig) {
560
+ return (await validateSaSig(sd.delegator, sdHash, sd.signature)) ? null : 'session-delegation signature validation failed (DEL-001)';
572
561
  }
573
- else {
574
- const sdCode = await publicClient.getCode({ address: sd.delegator });
575
- if (!sdCode || sdCode === '0x' || sdCode.length <= 2) {
576
- if (requireDeployed) {
577
- return rejectWith('session-delegation delegator SA not deployed — cannot verify ERC-1271 (DEL-001)', claims.delegation.delegator, eip712Hash);
578
- }
579
- }
580
- else {
581
- const magic = (await publicClient.readContract({
582
- address: sd.delegator,
583
- abi: ACCOUNT_ABI_ERC1271,
584
- functionName: 'isValidSignature',
585
- args: [sdHash, sd.signature],
586
- }));
587
- if (magic.toLowerCase() !== ERC1271_MAGIC) {
588
- return rejectWith('session-delegation erc1271 validation failed (DEL-001)', claims.delegation.delegator, eip712Hash);
589
- }
590
- }
562
+ const sdCode = await publicClient.getCode({ address: sd.delegator });
563
+ if (!sdCode || sdCode === '0x' || sdCode.length <= 2) {
564
+ return requireDeployed ? 'session-delegation delegator SA not deployed — cannot verify ERC-1271 (DEL-001)' : null;
591
565
  }
566
+ const magic = (await publicClient.readContract({
567
+ address: sd.delegator,
568
+ abi: ACCOUNT_ABI_ERC1271,
569
+ functionName: 'isValidSignature',
570
+ args: [sdHash, sd.signature],
571
+ }));
572
+ return magic.toLowerCase() !== ERC1271_MAGIC ? 'session-delegation erc1271 validation failed (DEL-001)' : null;
592
573
  }
593
574
  catch (e) {
594
- return rejectWith(`session-delegation signature check reverted: ${e instanceof Error ? e.message : e}`, claims.delegation.delegator, eip712Hash);
575
+ return `session-delegation signature check reverted: ${e instanceof Error ? e.message : e}`;
595
576
  }
577
+ };
578
+ // ONE ROUND TRIP, NOT FOUR. Root revocation, leaf revocation (DEL-002: the session-key binding is
579
+ // separately revocable and was once never checked — a revoked, e.g. compromised, session key is rejected
580
+ // as tightly as a revoked root), root signature and leaf signature are four independent reads; issued in
581
+ // series they were the verify's whole latency on every gated tool call — four provider round trips before
582
+ // a single record byte moved. They are issued together and JUDGED in the order they always were: root
583
+ // revocation, leaf revocation, root signature, the leaf's binding, leaf signature. A check that is not
584
+ // first to fail still ran, which it did before too; nothing is skipped and no verdict is weakened.
585
+ {
586
+ const leafRevocationHash = claims.sessionDelegation ? hashDelegation(claims.sessionDelegation, opts.chainId, opts.delegationManager) : null;
587
+ const [rootReason, leafReason, rootSig, leafSig] = await Promise.all([
588
+ revocationRejection(eip712Hash),
589
+ leafRevocationHash ? revocationRejection(leafRevocationHash) : Promise.resolve(null),
590
+ rootSignatureRejection(),
591
+ leafSignatureRejection(),
592
+ ]);
593
+ if (rootReason)
594
+ return rejectWith(rootReason, claims.delegation.delegator, eip712Hash);
595
+ if (leafReason)
596
+ return rejectWith(`session-delegation leaf: ${leafReason}`, claims.delegation.delegator, leafRevocationHash);
597
+ if (rootSig)
598
+ return rejectWith(rootSig, claims.delegation.delegator, eip712Hash);
599
+ if (bindErr)
600
+ return rejectWith(bindErr, claims.delegation.delegator, eip712Hash);
601
+ if (leafSig)
602
+ return rejectWith(leafSig, claims.delegation.delegator, eip712Hash);
603
+ }
604
+ if (sd) {
605
+ // Spec 408 §2.1 — THE LEAF'S OWN CAVEATS ARE JUDGED, strictly: its window (an expired leaf is refused as a
606
+ // leaf, not discovered as a root), its value (a token presentation moves nothing: 0), its audience
607
+ // (shape here; membership above). Before this, the leaf's caveats were never read.
608
+ const leafVerdicts = evaluateCaveats(sd.caveats, { timestamp: now, value: 0n }, opts.enforcerMap, {});
609
+ const leafDenied = leafVerdicts.find((v) => !v.allowed);
610
+ if (leafDenied)
611
+ return rejectWith(`session-delegation caveat denied: ${leafDenied.reason ?? 'denied'} (DEL-001)`, claims.delegation.delegator, eip712Hash);
596
612
  }
597
613
  // 4. caveat evaluation
598
614
  //