@agenticprimitives/a2a 0.0.0-alpha.2 → 0.0.0-alpha.20
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.
- package/CLAUDE.md +58 -21
- package/bin/a2a-conform.mjs +17 -0
- package/dist/agent.d.ts +171 -3
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +346 -62
- package/dist/agent.js.map +1 -1
- package/dist/auth.d.ts +72 -9
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +62 -19
- package/dist/auth.js.map +1 -1
- package/dist/authority-extension.d.ts +58 -0
- package/dist/authority-extension.d.ts.map +1 -0
- package/dist/authority-extension.js +70 -0
- package/dist/authority-extension.js.map +1 -0
- package/dist/card-audience.d.ts +87 -0
- package/dist/card-audience.d.ts.map +1 -0
- package/dist/card-audience.js +135 -0
- package/dist/card-audience.js.map +1 -0
- package/dist/client.d.ts +20 -8
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +69 -14
- package/dist/client.js.map +1 -1
- package/dist/cloudflare/index.d.ts.map +1 -1
- package/dist/cloudflare/index.js +10 -2
- package/dist/cloudflare/index.js.map +1 -1
- package/dist/conform/index.d.ts +36 -0
- package/dist/conform/index.d.ts.map +1 -0
- package/dist/conform/index.js +232 -0
- package/dist/conform/index.js.map +1 -0
- package/dist/discovery.d.ts +4 -0
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +6 -2
- package/dist/discovery.js.map +1 -1
- package/dist/engagement.d.ts +37 -0
- package/dist/engagement.d.ts.map +1 -0
- package/dist/engagement.js +83 -0
- package/dist/engagement.js.map +1 -0
- package/dist/grant.d.ts +4 -2
- package/dist/grant.d.ts.map +1 -1
- package/dist/grant.js +21 -13
- package/dist/grant.js.map +1 -1
- package/dist/handoff.d.ts +42 -0
- package/dist/handoff.d.ts.map +1 -0
- package/dist/handoff.js +28 -0
- package/dist/handoff.js.map +1 -0
- package/dist/index.d.ts +24 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/payment-gate.d.ts +88 -0
- package/dist/payment-gate.d.ts.map +1 -0
- package/dist/payment-gate.js +47 -0
- package/dist/payment-gate.js.map +1 -0
- package/dist/runtime.d.ts +13 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +35 -10
- package/dist/runtime.js.map +1 -1
- package/dist/session-wire.d.ts +69 -0
- package/dist/session-wire.d.ts.map +1 -0
- package/dist/session-wire.js +170 -0
- package/dist/session-wire.js.map +1 -0
- package/dist/skill-handler.d.ts +26 -1
- package/dist/skill-handler.d.ts.map +1 -1
- package/dist/skill-handler.js.map +1 -1
- package/dist/standard/caller.d.ts +86 -0
- package/dist/standard/caller.d.ts.map +1 -0
- package/dist/standard/caller.js +159 -0
- package/dist/standard/caller.js.map +1 -0
- package/dist/standard/client.d.ts +50 -0
- package/dist/standard/client.d.ts.map +1 -0
- package/dist/standard/client.js +86 -0
- package/dist/standard/client.js.map +1 -0
- package/dist/standard/delegated.d.ts +119 -0
- package/dist/standard/delegated.d.ts.map +1 -0
- package/dist/standard/delegated.js +168 -0
- package/dist/standard/delegated.js.map +1 -0
- package/dist/standard/errors.d.ts +31 -0
- package/dist/standard/errors.d.ts.map +1 -0
- package/dist/standard/errors.js +75 -0
- package/dist/standard/errors.js.map +1 -0
- package/dist/standard/from-agent.d.ts +38 -0
- package/dist/standard/from-agent.d.ts.map +1 -0
- package/dist/standard/from-agent.js +109 -0
- package/dist/standard/from-agent.js.map +1 -0
- package/dist/standard/index.d.ts +9 -0
- package/dist/standard/index.d.ts.map +1 -0
- package/dist/standard/index.js +13 -0
- package/dist/standard/index.js.map +1 -0
- package/dist/standard/mount.d.ts +91 -0
- package/dist/standard/mount.d.ts.map +1 -0
- package/dist/standard/mount.js +181 -0
- package/dist/standard/mount.js.map +1 -0
- package/dist/standard/server.d.ts +105 -0
- package/dist/standard/server.d.ts.map +1 -0
- package/dist/standard/server.js +454 -0
- package/dist/standard/server.js.map +1 -0
- package/dist/standard/types.d.ts +186 -0
- package/dist/standard/types.d.ts.map +1 -0
- package/dist/standard/types.js +14 -0
- package/dist/standard/types.js.map +1 -0
- package/dist/subject-ask.d.ts +96 -0
- package/dist/subject-ask.d.ts.map +1 -0
- package/dist/subject-ask.js +45 -0
- package/dist/subject-ask.js.map +1 -0
- package/dist/subject-hop.d.ts +75 -0
- package/dist/subject-hop.d.ts.map +1 -0
- package/dist/subject-hop.js +170 -0
- package/dist/subject-hop.js.map +1 -0
- package/dist/task-store.d.ts +9 -3
- package/dist/task-store.d.ts.map +1 -1
- package/dist/task-store.js +12 -6
- package/dist/task-store.js.map +1 -1
- package/dist/wire-verify.d.ts +35 -0
- package/dist/wire-verify.d.ts.map +1 -0
- package/dist/wire-verify.js +51 -0
- package/dist/wire-verify.js.map +1 -0
- package/package.json +20 -6
- package/dist/jsonrpc.d.ts +0 -25
- package/dist/jsonrpc.d.ts.map +0 -1
- package/dist/jsonrpc.js +0 -52
- package/dist/jsonrpc.js.map +0 -1
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// SESSION WIRES — how an agent signs as an identity whose key it does not hold. Spec 350 §8 / spec 326.
|
|
2
|
+
//
|
|
3
|
+
// THE CALLER-SIGNATURE GAP, RESOLVED (spec 329 §3.1, generalized). A runtime holds no key for the identity
|
|
4
|
+
// it acts as — an org's DO holds no org key, a relying service must never custody the service agent it
|
|
5
|
+
// acts as (ADR-0019: a relying key is always a DELEGATE, never a custodian), a skills worker signs as
|
|
6
|
+
// `skills-agent` without holding it. Yet A2A needs per-message sender signatures and per-poll caller
|
|
7
|
+
// signatures that verify against THAT identity. A ceremony therefore mints a NARROW delegation —
|
|
8
|
+
// delegator = the identity, delegate = a KMS session key, allowedMethods = a pinned set of skill
|
|
9
|
+
// selectors (never the any-skill sentinel), allowedTargets pinned, timestamp-bounded — signed by the
|
|
10
|
+
// identity's own custody credential. The runtime stores the wire; NO raw key ever rests there; the KMS
|
|
11
|
+
// key signs each digest on demand.
|
|
12
|
+
//
|
|
13
|
+
// ON THE WIRE such a signature is the SESSION-WRAPPED form: `0x51` (a type byte no on-chain validator
|
|
14
|
+
// accepts — it fails closed anywhere but a gate that understands it) followed by hex(utf8(JSON({ wire,
|
|
15
|
+
// sig }))). A gate verifies it fail-closed PER MESSAGE: delegator === the claimed signer; timestamp window
|
|
16
|
+
// live; a pinned selector set that names the requested skill and never A2A_ANY_SKILL; the raw ECDSA sig
|
|
17
|
+
// recovers to the wire's delegate; the wire's own signature ERC-1271-verifies against the delegator; AND
|
|
18
|
+
// the wire is unrevoked on chain — so a custodian's revocation kills the authority at every gate, now.
|
|
19
|
+
//
|
|
20
|
+
// WHY THIS IS HERE. Four copies of this file existed across two repos (demo-a2a's session-wire.ts and
|
|
21
|
+
// org-wire.ts, skills-a2a's service-wire.ts, and a sibling worker's). "Copy the wire implementation, do not
|
|
22
|
+
// invent a third" was the instruction, and the count had already reached four. It is an A2A signature
|
|
23
|
+
// format that consumes this package's own `skillSelector`; it belongs here, and the apps now consume it.
|
|
24
|
+
// What STAYS in the apps is policy — which caveat SHAPE counts as stewardship vs member access, which
|
|
25
|
+
// contracts a stewardship wire must pin. `org-wire.ts`'s `hasStewardshipShape` is a positive identity
|
|
26
|
+
// test no generic layer can express, and it does not move.
|
|
27
|
+
import { hashMessage, keccak256, recoverAddress, toBytes } from 'viem';
|
|
28
|
+
import { decodeAllowedMethodsTerms, decodeTimestampTerms } from '@agenticprimitives/delegation';
|
|
29
|
+
import { A2A_ANY_SKILL, skillSelector } from './grant.js';
|
|
30
|
+
/** Signature type byte for the session-wrapped form. Unknown to AgentAccount `_validateSig` (fails closed
|
|
31
|
+
* on chain) and to every other verifier — only a gate that calls `verifySessionWrappedSignature` accepts
|
|
32
|
+
* it, and only after full verification. */
|
|
33
|
+
export const SESSION_WRAPPED_SIG_TYPE = '0x51';
|
|
34
|
+
const utf8ToHex = (s) => `0x${Array.from(new TextEncoder().encode(s), (b) => b.toString(16).padStart(2, '0')).join('')}`;
|
|
35
|
+
const hexToUtf8 = (h) => {
|
|
36
|
+
const clean = h.startsWith('0x') ? h.slice(2) : h;
|
|
37
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
38
|
+
for (let i = 0; i < bytes.length; i++)
|
|
39
|
+
bytes[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
40
|
+
return new TextDecoder().decode(bytes);
|
|
41
|
+
};
|
|
42
|
+
/** Wrap a raw session-key ECDSA signature with the wire that authorizes it. */
|
|
43
|
+
export function wrapSessionSignature(wire, sig) {
|
|
44
|
+
return (SESSION_WRAPPED_SIG_TYPE + utf8ToHex(JSON.stringify({ wire, sig })).slice(2));
|
|
45
|
+
}
|
|
46
|
+
/** Parse the session-wrapped form; null for any other signature shape (callers then use the standard
|
|
47
|
+
* ERC-1271 path — one detector, no ambiguity). */
|
|
48
|
+
export function parseSessionWrappedSignature(signature) {
|
|
49
|
+
if (!signature?.startsWith(SESSION_WRAPPED_SIG_TYPE) || signature.length <= SESSION_WRAPPED_SIG_TYPE.length)
|
|
50
|
+
return null;
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(hexToUtf8(`0x${signature.slice(SESSION_WRAPPED_SIG_TYPE.length)}`));
|
|
53
|
+
if (!parsed?.wire?.delegator || !parsed.wire.delegate || !parsed.wire.signature || !parsed.sig)
|
|
54
|
+
return null;
|
|
55
|
+
return { wire: parsed.wire, sig: parsed.sig };
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function wireToDelegation(w) {
|
|
62
|
+
return {
|
|
63
|
+
delegator: w.delegator,
|
|
64
|
+
delegate: w.delegate,
|
|
65
|
+
authority: w.authority,
|
|
66
|
+
caveats: w.caveats.map((c) => ({ enforcer: c.enforcer, terms: c.terms, args: (c.args ?? '0x') })),
|
|
67
|
+
salt: BigInt(w.salt),
|
|
68
|
+
signature: w.signature,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function delegationToWire(d) {
|
|
72
|
+
return {
|
|
73
|
+
delegator: d.delegator, delegate: d.delegate, authority: d.authority,
|
|
74
|
+
caveats: d.caveats.map((c) => ({ enforcer: c.enforcer, terms: c.terms, ...(c.args && c.args !== '0x' ? { args: c.args } : {}) })),
|
|
75
|
+
salt: d.salt.toString(), signature: d.signature,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Shape check for a session wire (at ceremony store time AND at every gate hit): timestamp-bounded, a
|
|
80
|
+
* pinned allowedMethods set that never carries the any-skill sentinel and — when `skill` is given — names
|
|
81
|
+
* that skill's selector.
|
|
82
|
+
*
|
|
83
|
+
* `skill` should be passed wherever the request names one: a wire minted for one rail must not authorize
|
|
84
|
+
* another. It is omitted only on the read/control path (`tasks/get`, `tasks/cancel`,
|
|
85
|
+
* `pushNotificationConfig/set`), whose digest binds a method and a taskId, not a skill. That omission is
|
|
86
|
+
* narrow rather than lax — the wire must still be pinned, live, ERC-1271-valid and unrevoked, and the task
|
|
87
|
+
* runtime independently requires the caller to BE a party to the task.
|
|
88
|
+
*/
|
|
89
|
+
export function checkSessionWireShape(wire, enforcers, nowSec, opts) {
|
|
90
|
+
const byEnforcer = (addr) => (wire.caveats ?? []).find((c) => (c.enforcer ?? '').toLowerCase() === addr.toLowerCase());
|
|
91
|
+
const tsCav = byEnforcer(enforcers.timestamp);
|
|
92
|
+
if (!tsCav?.terms)
|
|
93
|
+
return 'session wire must be timestamp-bounded';
|
|
94
|
+
try {
|
|
95
|
+
const win = decodeTimestampTerms(tsCav.terms);
|
|
96
|
+
const now = BigInt(nowSec);
|
|
97
|
+
if (now < win.validAfter || now >= win.validUntil)
|
|
98
|
+
return 'session wire outside its timestamp window';
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return 'session wire timestamp terms undecodable';
|
|
102
|
+
}
|
|
103
|
+
const amCav = byEnforcer(enforcers.allowedMethods);
|
|
104
|
+
if (!amCav?.terms)
|
|
105
|
+
return 'session wire must carry an allowedMethods caveat';
|
|
106
|
+
try {
|
|
107
|
+
const selectors = decodeAllowedMethodsTerms(amCav.terms).map((s) => s.toLowerCase());
|
|
108
|
+
// A PINNED SET, never the any-skill sentinel. A leaked delegate key can send only what the custodian
|
|
109
|
+
// enumerated; `A2A_ANY_SKILL` is the line between "these operations" and "anything this agent can do".
|
|
110
|
+
if (selectors.some((s) => s === A2A_ANY_SKILL.toLowerCase()))
|
|
111
|
+
return 'session wire must never carry the any-skill sentinel';
|
|
112
|
+
if (selectors.length === 0)
|
|
113
|
+
return 'session wire allowedMethods must name at least one selector';
|
|
114
|
+
if (opts?.skill) {
|
|
115
|
+
const want = skillSelector(opts.skill).toLowerCase();
|
|
116
|
+
if (!selectors.includes(want))
|
|
117
|
+
return `session wire allowedMethods does not name the ${opts.skill} selector`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return 'session wire allowedMethods terms undecodable';
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Verify a session-wrapped signature for `signer` over `digest`, fail-closed on every leg. The on-chain
|
|
127
|
+
* checks are the SAME injected ones the standard gate uses (`OnChainChecks`) — revocation is immediate.
|
|
128
|
+
* Pass `skill` whenever the request names one.
|
|
129
|
+
*/
|
|
130
|
+
export async function verifySessionWrappedSignature(args) {
|
|
131
|
+
const parsed = parseSessionWrappedSignature(args.signature);
|
|
132
|
+
if (!parsed)
|
|
133
|
+
return false;
|
|
134
|
+
const { wire, sig } = parsed;
|
|
135
|
+
if (wire.delegator.toLowerCase() !== args.signer.toLowerCase())
|
|
136
|
+
return false;
|
|
137
|
+
const shapeOpts = args.skill ? { skill: args.skill } : undefined;
|
|
138
|
+
if (checkSessionWireShape(wire, args.enforcers, Math.floor((args.now ?? Date.now()) / 1000), shapeOpts) !== null)
|
|
139
|
+
return false;
|
|
140
|
+
// The raw sig must recover to the wire's delegate (the KMS session key). Accept both raw-digest and
|
|
141
|
+
// eth-signed-message recovery, mirroring AgentAccount._verifyEcdsa.
|
|
142
|
+
const delegate = wire.delegate.toLowerCase();
|
|
143
|
+
let recovered = false;
|
|
144
|
+
try {
|
|
145
|
+
recovered = (await recoverAddress({ hash: args.digest, signature: sig })).toLowerCase() === delegate;
|
|
146
|
+
}
|
|
147
|
+
catch { /* try wrapped */ }
|
|
148
|
+
if (!recovered) {
|
|
149
|
+
try {
|
|
150
|
+
recovered = (await recoverAddress({ hash: hashMessage({ raw: toBytes(args.digest) }), signature: sig })).toLowerCase() === delegate;
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (!recovered)
|
|
157
|
+
return false;
|
|
158
|
+
const d = wireToDelegation(wire);
|
|
159
|
+
try {
|
|
160
|
+
if (await args.isRevoked(d))
|
|
161
|
+
return false; // custodian revoke ⇒ immediate kill at every gate
|
|
162
|
+
return await args.verifyDelegationSig(d);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return false; // fail-closed on chain-read failure (ADR-0013)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** keccak over stable-JSON — the a2a body-hash convention (equals the task runtime's `hashBody`). */
|
|
169
|
+
export const sessionBodyHash = (data) => keccak256(toBytes(JSON.stringify(data ?? null)));
|
|
170
|
+
//# sourceMappingURL=session-wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-wire.js","sourceRoot":"","sources":["../src/session-wire.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,EAAE;AACF,2GAA2G;AAC3G,uGAAuG;AACvG,sGAAsG;AACtG,qGAAqG;AACrG,iGAAiG;AACjG,iGAAiG;AACjG,qGAAqG;AACrG,uGAAuG;AACvG,mCAAmC;AACnC,EAAE;AACF,sGAAsG;AACtG,uGAAuG;AACvG,2GAA2G;AAC3G,wGAAwG;AACxG,yGAAyG;AACzG,uGAAuG;AACvG,EAAE;AACF,sGAAsG;AACtG,4GAA4G;AAC5G,sGAAsG;AACtG,yGAAyG;AACzG,sGAAsG;AACtG,sGAAsG;AACtG,2DAA2D;AAC3D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAA0B,MAAM,MAAM,CAAC;AAC/F,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAmB,MAAM,+BAA+B,CAAC;AACjH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAY1D;;4CAE4C;AAC5C,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE/C,MAAM,SAAS,GAAG,CAAC,CAAS,EAAO,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAS,CAAC;AAC7I,MAAM,SAAS,GAAG,CAAC,CAAS,EAAU,EAAE;IACtC,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9F,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,IAAsB,EAAE,GAAQ;IACnE,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAQ,CAAC;AAC/F,CAAC;AAED;mDACmD;AACnD,MAAM,UAAU,4BAA4B,CAAC,SAAiB;IAC5D,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,wBAAwB,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,wBAAwB,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,SAAS,CAAC,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAA2C,CAAC;QACxI,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAC5G,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAmB;IAClD,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,SAAS,EAAE,CAAC,CAAC,SAAS;QACtB,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAQ,EAAE,CAAC,CAAC;QACxG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QACpB,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAa;IAC5C,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS;QACpE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,KAAY,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/I,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAgB;KACvD,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAsB,EACtB,SAAwD,EACxD,MAAc,EACd,IAAyB;IAEzB,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/H,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,EAAE,KAAK;QAAE,OAAO,wCAAwC,CAAC;IACnE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,IAAI,GAAG,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,IAAI,GAAG,CAAC,UAAU;YAAE,OAAO,2CAA2C,CAAC;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,0CAA0C,CAAC;IACpD,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,EAAE,KAAK;QAAE,OAAO,kDAAkD,CAAC;IAC7E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACrF,qGAAqG;QACrG,uGAAuG;QACvG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,sDAAsD,CAAC;QAC5H,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,6DAA6D,CAAC;QACjG,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YACrD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,OAAO,iDAAiD,IAAI,CAAC,KAAK,WAAW,CAAC;QAC/G,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,+CAA+C,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,IAWnD;IACC,MAAM,MAAM,GAAG,4BAA4B,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAC7B,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACjE,IAAI,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/H,oGAAoG;IACpG,oEAAoE;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,CAAC;QAAC,SAAS,GAAG,CAAC,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACzI,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,IAAI,CAAC;YAAC,SAAS,GAAG,CAAC,MAAM,cAAc,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IACtK,CAAC;IACD,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,MAAM,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,kDAAkD;QAC7F,OAAO,MAAM,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC,CAAC,+CAA+C;IAC/D,CAAC;AACH,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAa,EAAO,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/skill-handler.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Address, Hex } from '@agenticprimitives/types';
|
|
2
2
|
import type { Delegation } from '@agenticprimitives/delegation';
|
|
3
3
|
import type { VaultRef } from './types.js';
|
|
4
|
+
import type { SkillPayment } from './payment-gate.js';
|
|
4
5
|
/** Minimal vault seam — the consumer wires demo-mcp vault read/write over a delegation. FR-3.4: a handler
|
|
5
6
|
* delivers a result into ANOTHER principal's vault by passing a `delegation` THAT principal granted
|
|
6
7
|
* (delegator == the record owner); the consumer routes it through `callMcpToolViaDelegation` so demo-mcp
|
|
@@ -16,11 +17,16 @@ export interface VaultClient {
|
|
|
16
17
|
delegation?: Delegation;
|
|
17
18
|
}): Promise<VaultRef>;
|
|
18
19
|
}
|
|
19
|
-
/** Minimal MCP seam — call a tool via the delegation token (reuses the a2a→mcp leg, W4).
|
|
20
|
+
/** Minimal MCP seam — call a tool via the delegation token (reuses the a2a→mcp leg, W4). Symmetric with
|
|
21
|
+
* `VaultClient`: pass the task's `delegation` (the grant THAT principal signed) so the composed MCP call
|
|
22
|
+
* rides the on-chain authority (ADR-0041); the consumer routes it through `callMcpToolViaDelegation`. Omit
|
|
23
|
+
* `delegation` only for an agent-self call that needs no principal grant. This is the port the Ring-0
|
|
24
|
+
* orchestration loop's `ToolInvoker` wraps (ADR-0044). */
|
|
20
25
|
export interface McpClient {
|
|
21
26
|
callTool(args: {
|
|
22
27
|
tool: string;
|
|
23
28
|
toolArgs?: Record<string, unknown>;
|
|
29
|
+
delegation?: Delegation;
|
|
24
30
|
}): Promise<unknown>;
|
|
25
31
|
}
|
|
26
32
|
/** Thrown by `requestAuth` to suspend a task pending a fresh/again-scoped delegation (FR-3.5). The
|
|
@@ -67,6 +73,8 @@ export interface SkillContext {
|
|
|
67
73
|
bodyContentType?: string;
|
|
68
74
|
disclosurePolicy?: string;
|
|
69
75
|
caseId?: Hex;
|
|
76
|
+
/** URI-keyed A2A extension metadata to record on the artifact (e.g. skill-provenance). */
|
|
77
|
+
metadata?: Record<string, unknown>;
|
|
70
78
|
}): Promise<Hex>;
|
|
71
79
|
/** Suspend pending a fresh grant — throws `AuthRequired`. */
|
|
72
80
|
requestAuth(reason: string): never;
|
|
@@ -79,8 +87,25 @@ export interface SkillResult {
|
|
|
79
87
|
artifactIds?: Hex[];
|
|
80
88
|
error?: string;
|
|
81
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Who may SEE a skill on an agent card (spec 338 §8, ADR-0056 §6). Mirrors `surface-catalog`'s
|
|
92
|
+
* `SurfaceExposure` structurally — not imported, so `a2a` stays dependency-light.
|
|
93
|
+
*
|
|
94
|
+
* Absent ⇒ `public`, preserving pre-spec-338 behaviour. Visibility is NOT authorization: a skill
|
|
95
|
+
* hidden from a card is still gated by delegation + policy if someone guesses its name, and a skill
|
|
96
|
+
* shown on a card grants nothing.
|
|
97
|
+
*/
|
|
98
|
+
export type SkillExposure = 'public' | 'authenticated' | 'private' | 'service-only';
|
|
82
99
|
export interface SkillHandler {
|
|
83
100
|
skill: string;
|
|
101
|
+
/** Card visibility. Omit ⇒ `public`. See `SkillExposure`. */
|
|
102
|
+
exposure?: SkillExposure;
|
|
103
|
+
/** For `exposure: 'private'` — canonical ids permitted to see it. Empty/absent ⇒ nobody. */
|
|
104
|
+
audience?: readonly string[];
|
|
105
|
+
/** PAY-A2A-1 — optional price. A priced skill is gated by the injected `PaymentGate` BEFORE `handle`
|
|
106
|
+
* runs; an unpaid request parks `input-required` with `x402.payment.*` metadata (the handler is never
|
|
107
|
+
* reached). Free skills omit this. */
|
|
108
|
+
payment?: SkillPayment;
|
|
84
109
|
handle(ctx: SkillContext): Promise<SkillResult>;
|
|
85
110
|
}
|
|
86
111
|
/** Index handlers by skill name; reject duplicate registrations. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-handler.d.ts","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-handler.d.ts","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-handler.js","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skill-handler.js","sourceRoot":"","sources":["../src/skill-handler.ts"],"names":[],"mappings":"AA2BA;yEACyE;AACzE,MAAM,OAAO,YAAa,SAAQ,KAAK;IACT;IAA5B,YAA4B,UAAkB;QAC5C,KAAK,CAAC,kBAAkB,UAAU,EAAE,CAAC,CAAC;QADZ,eAAU,GAAV,UAAU,CAAQ;QAE5C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAcD;;mFAEmF;AACnF,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACb;IAA5B,YAA4B,OAAuB;QACjD,KAAK,CAAC,sBAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QADpB,YAAO,GAAP,OAAO,CAAgB;QAEjD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AA6DD,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CAAC,QAAwB;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC5C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7E,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type Address, type Hex } from 'viem';
|
|
2
|
+
import type { Delegation } from '@agenticprimitives/delegation';
|
|
3
|
+
import { type DelegationWireV1 } from '../session-wire.js';
|
|
4
|
+
import type { Principal } from './server.js';
|
|
5
|
+
/** The Authorization scheme an agent presents its session wire under. */
|
|
6
|
+
export declare const SESSION_AUTH_SCHEME = "A2A-Session";
|
|
7
|
+
/** The skill a session wire must pin to reach the standard surface: asking this agent, and nothing else.
|
|
8
|
+
* A wire that names other selectors and not this one is refused — pinning is the point. */
|
|
9
|
+
export declare const STANDARD_SURFACE_SKILL = "harness.ask";
|
|
10
|
+
/** What a caller signs. Every field is bound: a captured assertion cannot be replayed onto another method,
|
|
11
|
+
* another body, another host, or a later moment. `issuedAt` is IN the digest and checked (stale / ahead refused,
|
|
12
|
+
* the digest claimed once) — the wire path's freshness field that the deleted JSON-RPC dispatcher once dropped
|
|
13
|
+
* (audit a2a-issuedat-dropped-in-dispatch; the folded wire of spec 372 S4 is where the check lives now). */
|
|
14
|
+
export interface CallerAssertionV1 {
|
|
15
|
+
/** The Smart Agent the caller acts AS — must equal the wire's delegator. */
|
|
16
|
+
agent: string;
|
|
17
|
+
/** The A2A method this assertion is for. */
|
|
18
|
+
method: string;
|
|
19
|
+
/** keccak256 over the raw JSON-RPC request body. */
|
|
20
|
+
bodyHash: Hex;
|
|
21
|
+
/** Seconds since the epoch. */
|
|
22
|
+
issuedAt: number;
|
|
23
|
+
/** The origin the request is addressed to (`https://host`), so an assertion for one agent's host is not
|
|
24
|
+
* usable at another's. */
|
|
25
|
+
audience: string;
|
|
26
|
+
/** The `0x51`-wrapped session signature over `callerAssertionDigest(...)`. */
|
|
27
|
+
signature: string;
|
|
28
|
+
}
|
|
29
|
+
/** The digest a caller signs — keccak over stable JSON, the a2a body-hash convention. */
|
|
30
|
+
export declare function callerAssertionDigest(a: Omit<CallerAssertionV1, 'signature'>): Hex;
|
|
31
|
+
/** keccak over the raw request body, exactly as it arrived — never over a re-serialized parse. */
|
|
32
|
+
export declare const requestBodyHash: (raw: string) => Hex;
|
|
33
|
+
/** Build the `Authorization` header value a runtime sends. */
|
|
34
|
+
export declare function sessionAuthorizationHeader(a: CallerAssertionV1): string;
|
|
35
|
+
/** Read an `A2A-Session` header. Returns null for any other scheme (a `Bearer` is a person's, not ours) and
|
|
36
|
+
* for anything malformed — never a partial assertion. */
|
|
37
|
+
export declare function parseSessionAuthorization(header: string | null | undefined): CallerAssertionV1 | null;
|
|
38
|
+
export interface SessionWirePrincipalDeps {
|
|
39
|
+
/** The enforcer addresses the wire's caveats must carry (this deployment's). */
|
|
40
|
+
enforcers: {
|
|
41
|
+
timestamp: string;
|
|
42
|
+
allowedMethods: string;
|
|
43
|
+
};
|
|
44
|
+
/** ERC-1271 / ECDSA verification of the wire against its delegator. */
|
|
45
|
+
verifyDelegationSig: (d: Delegation) => Promise<boolean>;
|
|
46
|
+
/** On-chain revocation — a custodian's revoke kills the caller at the next request. */
|
|
47
|
+
isRevoked: (d: Delegation) => Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Verify an assertion the agent signed DIRECTLY — ERC-1271 against its own account, no session key in
|
|
50
|
+
* between. Some agents can do that (a relayer holding the SA's credential, a persona in this estate) and
|
|
51
|
+
* before the fold they proved themselves exactly this way, with `caller` + `signature` on the wire.
|
|
52
|
+
*
|
|
53
|
+
* NOT A FALLBACK (ADR-0013). The signature's own type byte chooses: `0x51` is session-wrapped and takes
|
|
54
|
+
* the wire path; anything else takes this one. Neither runs because the other failed, and omitting this
|
|
55
|
+
* means a direct signature is simply not admitted.
|
|
56
|
+
*/
|
|
57
|
+
verifyAgentSignature?: (agent: Address, digest: Hex, signature: Hex) => Promise<boolean>;
|
|
58
|
+
/** How old an assertion may be (default 120 s). */
|
|
59
|
+
maxAgeSec?: number;
|
|
60
|
+
/** Tolerated clock skew for an assertion dated ahead (default 30 s). */
|
|
61
|
+
skewSec?: number;
|
|
62
|
+
now?: () => number;
|
|
63
|
+
/**
|
|
64
|
+
* Spend an assertion, once. Returns true when THIS call claimed it and false when it was already spent.
|
|
65
|
+
* The default is an in-isolate map, which is not replay protection where requests fan out across
|
|
66
|
+
* isolates — bind the estate's single writer (the agent's own object) in production.
|
|
67
|
+
*/
|
|
68
|
+
claim?: (digest: Hex, expiresAtMs: number) => Promise<boolean>;
|
|
69
|
+
/** Told why a caller was refused — for the operator's log, never for the caller (a refusal says only
|
|
70
|
+
* that it was refused; which leg failed is not a fact an unauthenticated caller is owed). */
|
|
71
|
+
onRefused?: (reason: string, agent?: string) => void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The `principal` implementation for agents. Returns `{ agent, kind: 'agent' }` on every leg passing, and
|
|
75
|
+
* `null` otherwise — the server answers 401 and no method runs.
|
|
76
|
+
*
|
|
77
|
+
* SINGLE-USE. An accepted assertion's digest is SPENT: a captured request cannot be replayed while it is
|
|
78
|
+
* still fresh. With `claim` bound to the estate's single writer this holds everywhere; without it, only
|
|
79
|
+
* within this isolate — which on a fanned-out edge is no protection at all, and was observed live before
|
|
80
|
+
* the ledger existed. The claim happens AFTER the signature verifies, so an unauthenticated caller can
|
|
81
|
+
* spend nothing and write nothing.
|
|
82
|
+
*/
|
|
83
|
+
export declare function sessionWirePrincipal(deps: SessionWirePrincipalDeps): (request: Request) => Promise<Principal | null>;
|
|
84
|
+
/** Re-export so a client can build a wire-signed call without reaching past the standard surface. */
|
|
85
|
+
export type { DelegationWireV1 };
|
|
86
|
+
//# sourceMappingURL=caller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller.d.ts","sourceRoot":"","sources":["../../src/standard/caller.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAsB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAA+D,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD;4FAC4F;AAC5F,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;6GAG6G;AAC7G,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,GAAG,CAAC;IACd,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB;+BAC2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,yFAAyF;AACzF,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,GAAG,GAAG,CASlF;AAED,kGAAkG;AAClG,eAAO,MAAM,eAAe,QAAS,MAAM,KAAG,GAA8B,CAAC;AAQ7E,8DAA8D;AAC9D,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEvE;AAED;0DAC0D;AAC1D,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,iBAAiB,GAAG,IAAI,CAerG;AAED,MAAM,WAAW,wBAAwB;IACvC,gFAAgF;IAChF,SAAS,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,uEAAuE;IACvE,mBAAmB,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,uFAAuF;IACvF,SAAS,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C;;;;;;;;OAQG;IACH,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzF,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D;kGAC8F;IAC9F,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,wBAAwB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA4DpH;AAED,qGAAqG;AACrG,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// THE RUNTIME AS ITS OWN CALLER — spec 372 S3c.
|
|
2
|
+
//
|
|
3
|
+
// A person reaches the standard surface with a Home session bearer. An outside runtime — Claude Code, Goose,
|
|
4
|
+
// a deploy bot — has no Home session and must never be given one: it is not a person, and a bearer minted for
|
|
5
|
+
// a person is exactly the credential-sharing this estate exists to avoid. What it holds instead is what every
|
|
6
|
+
// agent here holds: a SESSION WIRE (spec 350 §8) — a narrow delegation from its own Smart Agent to a key it
|
|
7
|
+
// controls, timestamp-bounded, pinning the one skill it may exercise, signed by the agent's custody credential
|
|
8
|
+
// and revocable on chain by that custodian at any moment.
|
|
9
|
+
//
|
|
10
|
+
// So the runtime signs each request with that key and presents the wire beside it. The server verifies, per
|
|
11
|
+
// request and fail-closed: the wire's delegator IS the agent claimed; the wire's shape is sound (bounded,
|
|
12
|
+
// pinned, never the any-skill sentinel); the raw signature recovers to the wire's delegate; the wire itself
|
|
13
|
+
// verifies against the delegator on chain (ERC-1271) and is NOT revoked. Revoking the wire kills the caller
|
|
14
|
+
// at the next request, everywhere, with no list to update.
|
|
15
|
+
//
|
|
16
|
+
// TWO SCHEMES, NOT A FALLBACK (ADR-0013). `Bearer` is a person's Home session; `A2A-Session` is an agent's
|
|
17
|
+
// wire. The scheme token in the header selects ONE mechanism, and it fails closed on its own terms — neither
|
|
18
|
+
// is ever tried after the other fails. Which one arrived says WHO is asking. Neither says what they may do.
|
|
19
|
+
import { keccak256, toBytes } from 'viem';
|
|
20
|
+
import { parseSessionWrappedSignature, verifySessionWrappedSignature } from '../session-wire.js';
|
|
21
|
+
/** The Authorization scheme an agent presents its session wire under. */
|
|
22
|
+
export const SESSION_AUTH_SCHEME = 'A2A-Session';
|
|
23
|
+
/** The skill a session wire must pin to reach the standard surface: asking this agent, and nothing else.
|
|
24
|
+
* A wire that names other selectors and not this one is refused — pinning is the point. */
|
|
25
|
+
export const STANDARD_SURFACE_SKILL = 'harness.ask';
|
|
26
|
+
/** The digest a caller signs — keccak over stable JSON, the a2a body-hash convention. */
|
|
27
|
+
export function callerAssertionDigest(a) {
|
|
28
|
+
return keccak256(toBytes(JSON.stringify({
|
|
29
|
+
v: 'ap.a2a.caller-assertion.v1',
|
|
30
|
+
agent: a.agent.toLowerCase(),
|
|
31
|
+
method: a.method,
|
|
32
|
+
bodyHash: a.bodyHash.toLowerCase(),
|
|
33
|
+
issuedAt: a.issuedAt,
|
|
34
|
+
audience: a.audience.replace(/\/$/, '').toLowerCase(),
|
|
35
|
+
})));
|
|
36
|
+
}
|
|
37
|
+
/** keccak over the raw request body, exactly as it arrived — never over a re-serialized parse. */
|
|
38
|
+
export const requestBodyHash = (raw) => keccak256(toBytes(raw));
|
|
39
|
+
const b64urlDecode = (s) => {
|
|
40
|
+
const padded = s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat((4 - (s.length % 4)) % 4);
|
|
41
|
+
return atob(padded);
|
|
42
|
+
};
|
|
43
|
+
const b64urlEncode = (s) => btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
44
|
+
/** Build the `Authorization` header value a runtime sends. */
|
|
45
|
+
export function sessionAuthorizationHeader(a) {
|
|
46
|
+
return `${SESSION_AUTH_SCHEME} ${b64urlEncode(JSON.stringify(a))}`;
|
|
47
|
+
}
|
|
48
|
+
/** Read an `A2A-Session` header. Returns null for any other scheme (a `Bearer` is a person's, not ours) and
|
|
49
|
+
* for anything malformed — never a partial assertion. */
|
|
50
|
+
export function parseSessionAuthorization(header) {
|
|
51
|
+
const m = new RegExp(`^${SESSION_AUTH_SCHEME}\\s+(.+)$`, 'i').exec((header ?? '').trim());
|
|
52
|
+
if (!m)
|
|
53
|
+
return null;
|
|
54
|
+
try {
|
|
55
|
+
const a = JSON.parse(b64urlDecode(m[1].trim()));
|
|
56
|
+
if (typeof a.agent !== 'string' || !/^0x[0-9a-fA-F]{40}$/.test(a.agent))
|
|
57
|
+
return null;
|
|
58
|
+
if (typeof a.method !== 'string' || !a.method)
|
|
59
|
+
return null;
|
|
60
|
+
if (typeof a.bodyHash !== 'string' || !/^0x[0-9a-fA-F]{64}$/.test(a.bodyHash))
|
|
61
|
+
return null;
|
|
62
|
+
if (typeof a.issuedAt !== 'number' || !Number.isFinite(a.issuedAt))
|
|
63
|
+
return null;
|
|
64
|
+
if (typeof a.audience !== 'string' || !a.audience)
|
|
65
|
+
return null;
|
|
66
|
+
if (typeof a.signature !== 'string' || !a.signature.startsWith('0x'))
|
|
67
|
+
return null;
|
|
68
|
+
return a;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The `principal` implementation for agents. Returns `{ agent, kind: 'agent' }` on every leg passing, and
|
|
76
|
+
* `null` otherwise — the server answers 401 and no method runs.
|
|
77
|
+
*
|
|
78
|
+
* SINGLE-USE. An accepted assertion's digest is SPENT: a captured request cannot be replayed while it is
|
|
79
|
+
* still fresh. With `claim` bound to the estate's single writer this holds everywhere; without it, only
|
|
80
|
+
* within this isolate — which on a fanned-out edge is no protection at all, and was observed live before
|
|
81
|
+
* the ledger existed. The claim happens AFTER the signature verifies, so an unauthenticated caller can
|
|
82
|
+
* spend nothing and write nothing.
|
|
83
|
+
*/
|
|
84
|
+
export function sessionWirePrincipal(deps) {
|
|
85
|
+
const maxAgeSec = deps.maxAgeSec ?? 120;
|
|
86
|
+
const skewSec = deps.skewSec ?? 30;
|
|
87
|
+
const now = deps.now ?? (() => Date.now());
|
|
88
|
+
const seen = new Map();
|
|
89
|
+
const refuse = (reason, agent) => { deps.onRefused?.(reason, agent); return null; };
|
|
90
|
+
return async (request) => {
|
|
91
|
+
const a = parseSessionAuthorization(request.headers.get('authorization'));
|
|
92
|
+
if (!a)
|
|
93
|
+
return null; // not our scheme — say nothing; another principal may own it
|
|
94
|
+
const nowSec = Math.floor(now() / 1000);
|
|
95
|
+
if (a.issuedAt > nowSec + skewSec)
|
|
96
|
+
return refuse('assertion is dated ahead', a.agent);
|
|
97
|
+
if (a.issuedAt < nowSec - maxAgeSec)
|
|
98
|
+
return refuse('assertion is stale', a.agent);
|
|
99
|
+
const audience = new URL(request.url).origin;
|
|
100
|
+
if (a.audience.replace(/\/$/, '').toLowerCase() !== audience.toLowerCase())
|
|
101
|
+
return refuse(`assertion is for ${a.audience}, not ${audience}`, a.agent);
|
|
102
|
+
let raw;
|
|
103
|
+
try {
|
|
104
|
+
raw = await request.clone().text();
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return refuse('request body unreadable', a.agent);
|
|
108
|
+
}
|
|
109
|
+
if (requestBodyHash(raw).toLowerCase() !== a.bodyHash.toLowerCase())
|
|
110
|
+
return refuse('assertion does not bind this body', a.agent);
|
|
111
|
+
let method;
|
|
112
|
+
try {
|
|
113
|
+
method = JSON.parse(raw).method;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return refuse('body is not JSON', a.agent);
|
|
117
|
+
}
|
|
118
|
+
if (method !== a.method)
|
|
119
|
+
return refuse(`assertion is for ${a.method}, body calls ${String(method)}`, a.agent);
|
|
120
|
+
const digest = callerAssertionDigest(a);
|
|
121
|
+
// A cheap local reject first, so a replay landing on the isolate that served the original costs no
|
|
122
|
+
// chain read; the authoritative claim is below, after the signature verifies.
|
|
123
|
+
for (const [k, at] of seen)
|
|
124
|
+
if (at < nowSec - maxAgeSec - skewSec)
|
|
125
|
+
seen.delete(k);
|
|
126
|
+
if (seen.has(digest))
|
|
127
|
+
return refuse('assertion already used', a.agent);
|
|
128
|
+
const wrapped = parseSessionWrappedSignature(a.signature) !== null;
|
|
129
|
+
const ok = wrapped
|
|
130
|
+
? await verifySessionWrappedSignature({
|
|
131
|
+
signer: a.agent.toLowerCase(),
|
|
132
|
+
digest,
|
|
133
|
+
signature: a.signature,
|
|
134
|
+
enforcers: deps.enforcers,
|
|
135
|
+
verifyDelegationSig: deps.verifyDelegationSig,
|
|
136
|
+
isRevoked: deps.isRevoked,
|
|
137
|
+
skill: STANDARD_SURFACE_SKILL,
|
|
138
|
+
now: now(),
|
|
139
|
+
}).catch(() => false)
|
|
140
|
+
: deps.verifyAgentSignature
|
|
141
|
+
? await deps.verifyAgentSignature(a.agent.toLowerCase(), digest, a.signature).catch(() => false)
|
|
142
|
+
: false;
|
|
143
|
+
if (!ok) {
|
|
144
|
+
return refuse(wrapped
|
|
145
|
+
? 'session wire did not verify (shape, signature, delegator or revocation)'
|
|
146
|
+
: deps.verifyAgentSignature ? 'the agent\'s own signature did not verify' : 'a direct agent signature is not admitted here', a.agent);
|
|
147
|
+
}
|
|
148
|
+
// SPENT, now that it is known to be genuine: the single writer decides who was first. A ledger that
|
|
149
|
+
// cannot be reached refuses the call — a replay window is not something to fail open into (ADR-0013).
|
|
150
|
+
if (deps.claim) {
|
|
151
|
+
const claimed = await deps.claim(digest, (a.issuedAt + maxAgeSec + skewSec) * 1000).catch(() => false);
|
|
152
|
+
if (!claimed)
|
|
153
|
+
return refuse('assertion already used', a.agent);
|
|
154
|
+
}
|
|
155
|
+
seen.set(digest, nowSec);
|
|
156
|
+
return { agent: a.agent.toLowerCase(), kind: 'agent' };
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=caller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"caller.js","sourceRoot":"","sources":["../../src/standard/caller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AgentCardV1, MessageV1, PartV1, TaskV1 } from './types.js';
|
|
2
|
+
export interface ResolvedAgentCard {
|
|
3
|
+
card: AgentCardV1;
|
|
4
|
+
/** SHA-256 over the card's bytes as served, hex — what a record pins and a later fetch is compared to. */
|
|
5
|
+
cardDigest: string;
|
|
6
|
+
/** The JSON-RPC 1.x interface the card publishes. */
|
|
7
|
+
endpoint: string;
|
|
8
|
+
cardUrl: string;
|
|
9
|
+
}
|
|
10
|
+
/** The A2A 1.0 JSON-RPC endpoint a card publishes (top-level `protocolVersion` covers a released card's interfaces). */
|
|
11
|
+
export declare function jsonRpcEndpointOf(card: AgentCardV1 & {
|
|
12
|
+
protocolVersion?: string;
|
|
13
|
+
}): string | null;
|
|
14
|
+
/** Fetch a card, digest its bytes, read its endpoint. A card without a 1.x JSON-RPC interface is refused. */
|
|
15
|
+
export declare function resolveAgentCard(cardUrl: string, fetchImpl?: typeof fetch, expectDigest?: string): Promise<ResolvedAgentCard>;
|
|
16
|
+
export interface StandardA2aClientOptions {
|
|
17
|
+
endpoint: string;
|
|
18
|
+
fetch?: typeof fetch;
|
|
19
|
+
/** Extra headers on every call — a bearer, a session wire. Never a mandate. */
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
}
|
|
22
|
+
export interface SendResult {
|
|
23
|
+
task?: TaskV1;
|
|
24
|
+
message?: MessageV1;
|
|
25
|
+
}
|
|
26
|
+
export interface StandardA2aClient {
|
|
27
|
+
sendMessage(parts: PartV1[], opts?: {
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
extensions?: string[];
|
|
30
|
+
contextId?: string;
|
|
31
|
+
taskId?: string;
|
|
32
|
+
}): Promise<SendResult>;
|
|
33
|
+
getTask(id: string): Promise<TaskV1>;
|
|
34
|
+
/** Poll until the task is terminal or the deadline passes; the last task seen is returned either way. */
|
|
35
|
+
awaitTask(id: string, opts?: {
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
everyMs?: number;
|
|
38
|
+
}): Promise<TaskV1>;
|
|
39
|
+
/** Send one text message and wait: the reply's text (status message + text artifacts) and the task. */
|
|
40
|
+
ask(text: string, opts?: {
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
text: string;
|
|
45
|
+
task?: TaskV1;
|
|
46
|
+
message?: MessageV1;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
|
49
|
+
export declare function createStandardA2aClient(o: StandardA2aClientOptions): StandardA2aClient;
|
|
50
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/standard/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAmB,MAAM,YAAY,CAAC;AAG1F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,0GAA0G;IAC1G,UAAU,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD,wHAAwH;AACxH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,GAAG,IAAI,CAIjG;AAED,6GAA6G;AAC7G,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,KAAa,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAY1I;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,UAAU;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE;AAIlE,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7J,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,yGAAyG;IACzG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxF,uGAAuG;IACvG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACrJ;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,wBAAwB,GAAG,iBAAiB,CA0CtF"}
|