@agenticprimitives/delegation 1.0.0-alpha.4 → 1.0.0-alpha.41
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/README.md +19 -2
- package/dist/authority-chain.d.ts +59 -0
- package/dist/authority-chain.d.ts.map +1 -0
- package/dist/authority-chain.js +70 -0
- package/dist/authority-chain.js.map +1 -0
- package/dist/caveats.d.ts +196 -1
- package/dist/caveats.d.ts.map +1 -1
- package/dist/caveats.js +374 -2
- package/dist/caveats.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/es256-evidence-minter.d.ts +28 -0
- package/dist/es256-evidence-minter.d.ts.map +1 -0
- package/dist/es256-evidence-minter.js +48 -0
- package/dist/es256-evidence-minter.js.map +1 -0
- package/dist/evaluator.d.ts +1 -1
- package/dist/evaluator.d.ts.map +1 -1
- package/dist/evaluator.js +102 -2
- package/dist/evaluator.js.map +1 -1
- package/dist/hash.d.ts +1 -1
- package/dist/hash.d.ts.map +1 -1
- package/dist/index.d.ts +40 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -8
- package/dist/index.js.map +1 -1
- package/dist/invocation-proof.d.ts +133 -0
- package/dist/invocation-proof.d.ts.map +1 -0
- package/dist/invocation-proof.js +157 -0
- package/dist/invocation-proof.js.map +1 -0
- package/dist/lineage.d.ts +70 -0
- package/dist/lineage.d.ts.map +1 -0
- package/dist/lineage.js +65 -0
- package/dist/lineage.js.map +1 -0
- package/dist/mandate-handlers.d.ts +15 -0
- package/dist/mandate-handlers.d.ts.map +1 -0
- package/dist/mandate-handlers.js +279 -0
- package/dist/mandate-handlers.js.map +1 -0
- package/dist/mandate.d.ts +265 -0
- package/dist/mandate.d.ts.map +1 -0
- package/dist/mandate.js +275 -0
- package/dist/mandate.js.map +1 -0
- package/dist/method-authorization.d.ts +120 -0
- package/dist/method-authorization.d.ts.map +1 -0
- package/dist/method-authorization.js +173 -0
- package/dist/method-authorization.js.map +1 -0
- package/dist/onchain.d.ts +40 -4
- package/dist/onchain.d.ts.map +1 -1
- package/dist/onchain.js +140 -6
- package/dist/onchain.js.map +1 -1
- package/dist/presentation-release.d.ts +94 -0
- package/dist/presentation-release.d.ts.map +1 -0
- package/dist/presentation-release.js +93 -0
- package/dist/presentation-release.js.map +1 -0
- package/dist/quorum.d.ts +26 -0
- package/dist/quorum.d.ts.map +1 -0
- package/dist/quorum.js +80 -0
- package/dist/quorum.js.map +1 -0
- package/dist/session-delegation.d.ts +34 -0
- package/dist/session-delegation.d.ts.map +1 -0
- package/dist/session-delegation.js +33 -0
- package/dist/session-delegation.js.map +1 -0
- package/dist/session-manager.d.ts +1 -2
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +15 -6
- package/dist/session-manager.js.map +1 -1
- package/dist/standing.d.ts +101 -0
- package/dist/standing.d.ts.map +1 -0
- package/dist/standing.js +132 -0
- package/dist/standing.js.map +1 -0
- package/dist/token.d.ts +89 -1
- package/dist/token.d.ts.map +1 -1
- package/dist/token.js +485 -123
- package/dist/token.js.map +1 -1
- package/dist/types.d.ts +141 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/dist/verify-authorization.d.ts +28 -0
- package/dist/verify-authorization.d.ts.map +1 -0
- package/dist/verify-authorization.js +73 -0
- package/dist/verify-authorization.js.map +1 -0
- package/package.json +25 -16
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { Address, Caveat, Delegation, EnforcerAddressMap, Hex } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Map a method NAME to the 4-byte selector `allowedMethods` checks: `keccak256(utf8(name))[:4]`.
|
|
4
|
+
*
|
|
5
|
+
* Lives here because this package owns `encodeAllowedMethodsTerms` — the name→selector mapping and
|
|
6
|
+
* the encoding that consumes it must never drift apart. `@agenticprimitives/a2a`'s `skillSelector`
|
|
7
|
+
* is this function plus the A2A "any skill" sentinel.
|
|
8
|
+
*/
|
|
9
|
+
export declare function methodSelector(name: string): Hex;
|
|
10
|
+
/** Injected on-chain reads. Both fail CLOSED — a read that errored did not verify (ADR-0013). */
|
|
11
|
+
export interface MethodAuthorizationChecks {
|
|
12
|
+
/** `DelegationManager.isRevoked(hashDelegation(d))`. */
|
|
13
|
+
isRevoked: (delegation: Delegation) => Promise<boolean>;
|
|
14
|
+
/** ERC-1271 / ERC-6492 / ECDSA via `UniversalSignatureValidator`. */
|
|
15
|
+
verifySignature: (args: {
|
|
16
|
+
signer: Address;
|
|
17
|
+
digest: Hex;
|
|
18
|
+
signature: Hex;
|
|
19
|
+
}) => Promise<boolean>;
|
|
20
|
+
/** The EIP-712 digest the delegator signed — normally `hashDelegation(d)`. */
|
|
21
|
+
delegationDigest: (delegation: Delegation) => Hex;
|
|
22
|
+
}
|
|
23
|
+
export interface AuthorizeMethodInput {
|
|
24
|
+
delegation: Delegation;
|
|
25
|
+
/** The party claiming to act. MUST be the delegation's delegate. */
|
|
26
|
+
delegate: Address;
|
|
27
|
+
/** The agent being acted FOR. MUST be the delegator, and must satisfy allowedTargets. */
|
|
28
|
+
target: Address;
|
|
29
|
+
/** 4-byte selector of the method, e.g. `skillSelector('agent.discovery.grant.issue')`. */
|
|
30
|
+
selector: Hex;
|
|
31
|
+
enforcers: EnforcerAddressMap;
|
|
32
|
+
checks: MethodAuthorizationChecks;
|
|
33
|
+
/** Unix seconds. Injected so the decision is deterministic and testable. */
|
|
34
|
+
now: number;
|
|
35
|
+
}
|
|
36
|
+
export type AuthorizeMethodResult = {
|
|
37
|
+
ok: true;
|
|
38
|
+
} | {
|
|
39
|
+
ok: false;
|
|
40
|
+
reason: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Decide whether `delegate` may perform `selector` on behalf of `target`.
|
|
44
|
+
*
|
|
45
|
+
* NEVER THROWS on a denial — returns a reason the caller keeps LOCAL. Planes that must not leak which
|
|
46
|
+
* check fired (private resolution) map every reason to one uniform wire code themselves.
|
|
47
|
+
*/
|
|
48
|
+
export declare function authorizeMethodDelegation(input: AuthorizeMethodInput): Promise<AuthorizeMethodResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Build the caveats a method authority needs — the exact mirror of what
|
|
51
|
+
* `authorizeMethodDelegation` reads back.
|
|
52
|
+
*
|
|
53
|
+
* WHY THIS SITS BESIDE THE VERIFIER: a minter and a verifier that live apart drift, and the drift is
|
|
54
|
+
* silent — the delegation still verifies as a signature, it just no longer authorizes what its issuer
|
|
55
|
+
* believed. Keeping both in one file means a change to one is a change you cannot make without seeing
|
|
56
|
+
* the other.
|
|
57
|
+
*
|
|
58
|
+
* NOTE WHAT `target` MEANS HERE: the agent being acted FOR, which is also the delegator. That is the
|
|
59
|
+
* opposite of the A2A reading, where the allowed target is the recipient you are CALLING. The
|
|
60
|
+
* encoding is identical; only the intent differs, so the distinction lives in the caller's naming and
|
|
61
|
+
* in `authorizeMethodDelegation`'s insistence that `delegator === target`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildMethodAuthorityCaveats(args: {
|
|
64
|
+
/** The agent being acted for. MUST equal the delegation's delegator. */
|
|
65
|
+
target: Address;
|
|
66
|
+
/** Method NAME, e.g. `agent.discovery.grant.issue`. Reduced via `methodSelector`. */
|
|
67
|
+
method: string;
|
|
68
|
+
enforcers: Pick<EnforcerAddressMap, 'timestamp' | 'allowedTargets' | 'allowedMethods'>;
|
|
69
|
+
/** Unix seconds. A window is MANDATORY — `authorizeMethodDelegation` refuses uncaveated grants. */
|
|
70
|
+
window: {
|
|
71
|
+
validAfter: number;
|
|
72
|
+
validUntil: number;
|
|
73
|
+
};
|
|
74
|
+
}): Caveat[];
|
|
75
|
+
/**
|
|
76
|
+
* Is this delegation LIVE and genuinely signed by the party it names?
|
|
77
|
+
*
|
|
78
|
+
* THE QUESTION THIS ANSWERS, AND THE ONE IT DOES NOT. "Does this party hold a valid, unrevoked,
|
|
79
|
+
* in-window delegation from that party" — the silent-reauth / login-grade question. It is NOT "may
|
|
80
|
+
* they do X": for that, `authorizeMethodDelegation`, which additionally pins target and method.
|
|
81
|
+
*
|
|
82
|
+
* WHY IT EXISTS. Apps kept writing this by hand, and the hand-rolled versions lost things. The one in
|
|
83
|
+
* `demo-sso-next` minted login-grade sessions while (a) never checking revocation, (b) never
|
|
84
|
+
* evaluating any caveat except timestamp, and (c) *falling through to the signature check* when the
|
|
85
|
+
* timestamp terms failed to parse — so malformed terms meant no window at all. Each omission is
|
|
86
|
+
* individually easy to make and invisible in review, which is exactly why this belongs in one place.
|
|
87
|
+
*
|
|
88
|
+
* ABOUT THE CAVEATS. Evaluated with a timestamp-only context, so `allowedTargets` / `allowedMethods`
|
|
89
|
+
* go INERT rather than denying — there is no target or selector to judge them against. That is
|
|
90
|
+
* correct for a liveness check and is precisely why the result must not be read as authorization: a
|
|
91
|
+
* delegation scoped to one method is *live* for every method. An unknown enforcer still DENIES.
|
|
92
|
+
*/
|
|
93
|
+
export interface VerifyLiveDelegationInput {
|
|
94
|
+
delegation: Delegation;
|
|
95
|
+
/** Refuse unless the delegation is FROM this party. */
|
|
96
|
+
expectedDelegator?: Address;
|
|
97
|
+
/** Refuse unless it is TO this party. */
|
|
98
|
+
expectedDelegate?: Address;
|
|
99
|
+
/**
|
|
100
|
+
* Caveat kinds the delegation MUST carry.
|
|
101
|
+
*
|
|
102
|
+
* The shape gate: a stewardship wire and a data grant are both valid delegations between the same
|
|
103
|
+
* pair, and accepting either where only one is meant is how a governance grant gets replayed as
|
|
104
|
+
* member access. Naming the required enforcer is what keeps them distinct.
|
|
105
|
+
*/
|
|
106
|
+
requiredEnforcers?: readonly Address[];
|
|
107
|
+
enforcers: EnforcerAddressMap;
|
|
108
|
+
checks: MethodAuthorizationChecks;
|
|
109
|
+
/** Unix seconds. Injected so the decision is deterministic. */
|
|
110
|
+
now: number;
|
|
111
|
+
}
|
|
112
|
+
export type VerifyLiveDelegationResult = {
|
|
113
|
+
ok: true;
|
|
114
|
+
digest: Hex;
|
|
115
|
+
} | {
|
|
116
|
+
ok: false;
|
|
117
|
+
reason: string;
|
|
118
|
+
};
|
|
119
|
+
export declare function verifyLiveDelegation(input: VerifyLiveDelegationInput): Promise<VerifyLiveDelegationResult>;
|
|
120
|
+
//# sourceMappingURL=method-authorization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-authorization.d.ts","sourceRoot":"","sources":["../src/method-authorization.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAiB,UAAU,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtG;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAEhD;AAED,iGAAiG;AACjG,MAAM,WAAW,yBAAyB;IACxC,wDAAwD;IACxD,SAAS,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,qEAAqE;IACrE,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,GAAG,CAAC;QAAC,SAAS,EAAE,GAAG,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9F,8EAA8E;IAC9E,gBAAgB,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,GAAG,CAAC;CACnD;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,UAAU,CAAC;IACvB,oEAAoE;IACpE,QAAQ,EAAE,OAAO,CAAC;IAClB,yFAAyF;IACzF,MAAM,EAAE,OAAO,CAAC;IAChB,0FAA0F;IAC1F,QAAQ,EAAE,GAAG,CAAC;IACd,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,yBAAyB,CAAC;IAClC,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAKlC;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CAwDhC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE;IAChD,wEAAwE;IACxE,MAAM,EAAE,OAAO,CAAC;IAChB,qFAAqF;IACrF,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC,kBAAkB,EAAE,WAAW,GAAG,gBAAgB,GAAG,gBAAgB,CAAC,CAAC;IACvF,mGAAmG;IACnG,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACpD,GAAG,MAAM,EAAE,CASX;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,UAAU,CAAC;IACvB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACvC,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,yBAAyB,CAAC;IAClC,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,0BAA0B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,GACzB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,0BAA0B,CAAC,CAmErC"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// Generic "may this delegate perform METHOD on behalf of TARGET?" (spec 338 W6-c).
|
|
2
|
+
//
|
|
3
|
+
// WHY THIS EXISTS: `authorizeA2aMessage` already answers exactly this question — but only for an A2A
|
|
4
|
+
// message, with a message id, replay reservation and body hash bound in. Other planes need the same
|
|
5
|
+
// decision without a message: may this steward PUBLISH for that agent, may it ISSUE a discovery grant
|
|
6
|
+
// for that agent.
|
|
7
|
+
//
|
|
8
|
+
// Rather than each plane inventing its own authority record — which is what
|
|
9
|
+
// `agent-resolution` did with `PublicationAuthorityRecordV1`, and what a discovery-authority record
|
|
10
|
+
// would have repeated — they compose THIS, which is the same delegation + caveat rail everything else
|
|
11
|
+
// uses. One authority mechanism, not three.
|
|
12
|
+
//
|
|
13
|
+
// The checks and their ORDER mirror `authorizeA2aMessage`:
|
|
14
|
+
// delegate identity → caveats (timestamp / allowedTargets / allowedMethods) → on-chain revocation
|
|
15
|
+
// → signature.
|
|
16
|
+
// Cheap structural checks first so an unauthorized caller cannot make us do chain reads.
|
|
17
|
+
import { keccak256, toBytes } from 'viem';
|
|
18
|
+
import { buildCaveat, encodeAllowedMethodsTerms, encodeAllowedTargetsTerms, encodeTimestampTerms, } from './caveats.js';
|
|
19
|
+
import { evaluateCaveats } from './evaluator.js';
|
|
20
|
+
/**
|
|
21
|
+
* Map a method NAME to the 4-byte selector `allowedMethods` checks: `keccak256(utf8(name))[:4]`.
|
|
22
|
+
*
|
|
23
|
+
* Lives here because this package owns `encodeAllowedMethodsTerms` — the name→selector mapping and
|
|
24
|
+
* the encoding that consumes it must never drift apart. `@agenticprimitives/a2a`'s `skillSelector`
|
|
25
|
+
* is this function plus the A2A "any skill" sentinel.
|
|
26
|
+
*/
|
|
27
|
+
export function methodSelector(name) {
|
|
28
|
+
return keccak256(toBytes(name)).slice(0, 10); // 0x + 8 hex = 4 bytes
|
|
29
|
+
}
|
|
30
|
+
const eq = (a, b) => !!a && !!b && a.toLowerCase() === b.toLowerCase();
|
|
31
|
+
/**
|
|
32
|
+
* Decide whether `delegate` may perform `selector` on behalf of `target`.
|
|
33
|
+
*
|
|
34
|
+
* NEVER THROWS on a denial — returns a reason the caller keeps LOCAL. Planes that must not leak which
|
|
35
|
+
* check fired (private resolution) map every reason to one uniform wire code themselves.
|
|
36
|
+
*/
|
|
37
|
+
export async function authorizeMethodDelegation(input) {
|
|
38
|
+
const d = input.delegation;
|
|
39
|
+
// 1. The delegation must be FROM the agent being acted for. A delegation by anyone else is
|
|
40
|
+
// irrelevant no matter how well-formed — this is the check that stops a steward appointing
|
|
41
|
+
// itself over an agent that never appointed it.
|
|
42
|
+
if (!eq(d.delegator, input.target)) {
|
|
43
|
+
return { ok: false, reason: 'delegation delegator is not the target agent' };
|
|
44
|
+
}
|
|
45
|
+
// 2. The delegate IS the actor (mirrors authorizeA2aMessage FR-4.1).
|
|
46
|
+
if (!eq(d.delegate, input.delegate)) {
|
|
47
|
+
return { ok: false, reason: 'delegation delegate is not the acting party' };
|
|
48
|
+
}
|
|
49
|
+
// 3. Caveats — the substrate's own evaluator, not a hand-rolled reading of terms. `target` and
|
|
50
|
+
// `selector` drive allowedTargets / allowedMethods; `timestamp` drives the window.
|
|
51
|
+
const ctx = {
|
|
52
|
+
timestamp: input.now,
|
|
53
|
+
target: input.target,
|
|
54
|
+
selector: input.selector,
|
|
55
|
+
};
|
|
56
|
+
const verdicts = evaluateCaveats(d.caveats, ctx, input.enforcers);
|
|
57
|
+
const denied = verdicts.find((v) => !v.allowed);
|
|
58
|
+
if (denied)
|
|
59
|
+
return { ok: false, reason: `caveat denied: ${denied.reason}` };
|
|
60
|
+
// 4. An UNCAVEATED delegation is refused for this use. Elsewhere a bare delegation may be
|
|
61
|
+
// meaningful; here it would mean "this steward may do anything, forever, for this agent", which
|
|
62
|
+
// is never what an operator intends to sign and is not something we should let them sign by
|
|
63
|
+
// omission.
|
|
64
|
+
if (d.caveats.length === 0) {
|
|
65
|
+
return { ok: false, reason: 'delegation carries no caveats — refuse an unbounded authority' };
|
|
66
|
+
}
|
|
67
|
+
// 5. Revocation, then signature. Both on-chain, both fail-closed.
|
|
68
|
+
let revoked = true;
|
|
69
|
+
try {
|
|
70
|
+
revoked = await input.checks.isRevoked(d);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
revoked = true; // could not confirm live ⇒ treat as revoked
|
|
74
|
+
}
|
|
75
|
+
if (revoked)
|
|
76
|
+
return { ok: false, reason: 'delegation is revoked' };
|
|
77
|
+
let valid = false;
|
|
78
|
+
try {
|
|
79
|
+
valid = await input.checks.verifySignature({
|
|
80
|
+
signer: d.delegator,
|
|
81
|
+
digest: input.checks.delegationDigest(d),
|
|
82
|
+
signature: d.signature,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
valid = false;
|
|
87
|
+
}
|
|
88
|
+
if (!valid)
|
|
89
|
+
return { ok: false, reason: 'delegation signature did not verify' };
|
|
90
|
+
return { ok: true };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build the caveats a method authority needs — the exact mirror of what
|
|
94
|
+
* `authorizeMethodDelegation` reads back.
|
|
95
|
+
*
|
|
96
|
+
* WHY THIS SITS BESIDE THE VERIFIER: a minter and a verifier that live apart drift, and the drift is
|
|
97
|
+
* silent — the delegation still verifies as a signature, it just no longer authorizes what its issuer
|
|
98
|
+
* believed. Keeping both in one file means a change to one is a change you cannot make without seeing
|
|
99
|
+
* the other.
|
|
100
|
+
*
|
|
101
|
+
* NOTE WHAT `target` MEANS HERE: the agent being acted FOR, which is also the delegator. That is the
|
|
102
|
+
* opposite of the A2A reading, where the allowed target is the recipient you are CALLING. The
|
|
103
|
+
* encoding is identical; only the intent differs, so the distinction lives in the caller's naming and
|
|
104
|
+
* in `authorizeMethodDelegation`'s insistence that `delegator === target`.
|
|
105
|
+
*/
|
|
106
|
+
export function buildMethodAuthorityCaveats(args) {
|
|
107
|
+
return [
|
|
108
|
+
buildCaveat(args.enforcers.timestamp, encodeTimestampTerms(args.window.validAfter, args.window.validUntil)),
|
|
109
|
+
buildCaveat(args.enforcers.allowedTargets, encodeAllowedTargetsTerms([args.target])),
|
|
110
|
+
buildCaveat(args.enforcers.allowedMethods, encodeAllowedMethodsTerms([methodSelector(args.method)])),
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
export async function verifyLiveDelegation(input) {
|
|
114
|
+
const d = input.delegation;
|
|
115
|
+
if (input.expectedDelegator && !eq(d.delegator, input.expectedDelegator)) {
|
|
116
|
+
return { ok: false, reason: 'delegation is not from the expected delegator' };
|
|
117
|
+
}
|
|
118
|
+
if (input.expectedDelegate && !eq(d.delegate, input.expectedDelegate)) {
|
|
119
|
+
return { ok: false, reason: 'delegation is not to the expected delegate' };
|
|
120
|
+
}
|
|
121
|
+
for (const required of input.requiredEnforcers ?? []) {
|
|
122
|
+
if (!d.caveats.some((c) => eq(c.enforcer, required))) {
|
|
123
|
+
return { ok: false, reason: `delegation does not carry the required caveat ${required}` };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (d.caveats.length === 0) {
|
|
127
|
+
// An unbounded delegation has no window, so "live" would mean "forever".
|
|
128
|
+
return { ok: false, reason: 'delegation carries no caveats — refuse an unbounded authority' };
|
|
129
|
+
}
|
|
130
|
+
// Timestamp-only context, with `enforceOnChain` — and that opt is doing real work, so read it:
|
|
131
|
+
//
|
|
132
|
+
// The evaluator is STRICT by default. A caveat it cannot judge (allowedTargets with no target,
|
|
133
|
+
// allowedMethods with no selector) DENIES rather than passing. That is the right default for an
|
|
134
|
+
// authorization decision and the wrong one here, because a liveness check has no target or selector
|
|
135
|
+
// to judge against — it would refuse every scoped delegation.
|
|
136
|
+
//
|
|
137
|
+
// `enforceOnChain: true` is the declaration that those caveats are enforced where they actually
|
|
138
|
+
// bite: on-chain at redeem. It is safe HERE and only here, because the answer this function returns
|
|
139
|
+
// is "authenticated", never "authorized". A caller that treats a live delegation as permission to
|
|
140
|
+
// act has misread the result, which is why the return type carries a digest and nothing else.
|
|
141
|
+
//
|
|
142
|
+
// A malformed term is still a DENY, not a fall-through — the exact hole the hand-rolled versions
|
|
143
|
+
// had. Unknown enforcers still DENY.
|
|
144
|
+
const verdicts = evaluateCaveats(d.caveats, { timestamp: input.now }, input.enforcers, { enforceOnChain: true });
|
|
145
|
+
const denied = verdicts.find((v) => !v.allowed);
|
|
146
|
+
if (denied)
|
|
147
|
+
return { ok: false, reason: `caveat denied: ${denied.reason}` };
|
|
148
|
+
const digest = input.checks.delegationDigest(d);
|
|
149
|
+
let revoked = true;
|
|
150
|
+
try {
|
|
151
|
+
revoked = await input.checks.isRevoked(d);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
revoked = true; // could not confirm live ⇒ treat as revoked
|
|
155
|
+
}
|
|
156
|
+
if (revoked)
|
|
157
|
+
return { ok: false, reason: 'delegation is revoked' };
|
|
158
|
+
let valid = false;
|
|
159
|
+
try {
|
|
160
|
+
valid = await input.checks.verifySignature({
|
|
161
|
+
signer: d.delegator,
|
|
162
|
+
digest,
|
|
163
|
+
signature: d.signature,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
valid = false;
|
|
168
|
+
}
|
|
169
|
+
if (!valid)
|
|
170
|
+
return { ok: false, reason: 'delegation signature did not verify' };
|
|
171
|
+
return { ok: true, digest };
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=method-authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method-authorization.js","sourceRoot":"","sources":["../src/method-authorization.ts"],"names":[],"mappings":"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"}
|
package/dist/onchain.d.ts
CHANGED
|
@@ -1,8 +1,44 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
|
|
1
|
+
import { type Hex, type Address } from 'viem';
|
|
2
|
+
import type { Delegation } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Validate a signature by `signer` over `digest`, connection-agnostically
|
|
5
|
+
* (spec 270 v4 / spec 287 §7). The verification primitive is selected by the
|
|
6
|
+
* signer's TYPE — a deterministic branch on whether the signer has code, NOT a
|
|
7
|
+
* try-strong-catch-weak fallback (ADR-0013):
|
|
8
|
+
* - **EOA** (no code) → local ECDSA `recoverAddress` (the deployed
|
|
9
|
+
* `UniversalSignatureValidator` reverts on bare EOAs, and a session-key
|
|
10
|
+
* delegate is typically an EOA — same local-recover path `token.ts` uses for
|
|
11
|
+
* the token's own session-key signature).
|
|
12
|
+
* - **Contract** (has code) → on-chain `UniversalSignatureValidator.isValidSig`
|
|
13
|
+
* (ERC-1271 deployed / ERC-6492 counterfactual) via one `eth_call`.
|
|
14
|
+
*
|
|
15
|
+
* Reusable signature surface (spec 287 injects this as the invocation-proof
|
|
16
|
+
* verifier). `readContract` only — no log scans (ADR-0012). Returns `false` on a
|
|
17
|
+
* recover/RPC error rather than throwing, so callers fail closed cleanly.
|
|
18
|
+
*/
|
|
19
|
+
export declare function verifyUniversalSignature(args: {
|
|
20
|
+
signer: Address;
|
|
21
|
+
digest: Hex;
|
|
22
|
+
signature: Hex;
|
|
23
|
+
rpcUrl: string;
|
|
24
|
+
universalSignatureValidator: Address;
|
|
25
|
+
}): Promise<boolean>;
|
|
26
|
+
/** Is this delegation hash revoked on-chain? The canonical, single mechanism (ADR-0013): reads the
|
|
27
|
+
* DelegationManager's `_revoked` map. Returns `false` if absent — never escalates to a second path. */
|
|
28
|
+
export declare function isRevoked(hash: Hex, opts: {
|
|
4
29
|
delegationManager: Address;
|
|
5
30
|
rpcUrl: string;
|
|
6
31
|
}): Promise<boolean>;
|
|
7
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Build the call that revokes a delegation on-chain: `DelegationManager.revokeDelegationByOwner(d)`.
|
|
34
|
+
* The caller (the delegator OR the delegate) submits this through their Smart Account's `execute`
|
|
35
|
+
* (this package owns delegation semantics, not tx/UserOp submission — agent-account/app layer does).
|
|
36
|
+
* Once mined, `isRevoked(hash)` is true and `redeemDelegation` reverts. The on-chain function
|
|
37
|
+
* re-verifies the delegation's signature, so a forged hash cannot be marked revoked.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildRevokeDelegationCall(delegation: Delegation, delegationManager: Address): {
|
|
40
|
+
to: Address;
|
|
41
|
+
value: bigint;
|
|
42
|
+
data: Hex;
|
|
43
|
+
};
|
|
8
44
|
//# sourceMappingURL=onchain.d.ts.map
|
package/dist/onchain.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onchain.d.ts","sourceRoot":"","sources":["../src/onchain.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"onchain.d.ts","sourceRoot":"","sources":["../src/onchain.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgE,KAAK,GAAG,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAC5G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA2B7C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B,EAAE,OAAO,CAAC;CACtC,GAAG,OAAO,CAAC,OAAO,CAAC,CA6BnB;AAkCD;wGACwG;AACxG,wBAAsB,SAAS,CAC7B,IAAI,EAAE,GAAG,EACT,IAAI,EAAE;IAAE,iBAAiB,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,UAAU,EACtB,iBAAiB,EAAE,OAAO,GACzB;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,CAAA;CAAE,CAgB3C"}
|
package/dist/onchain.js
CHANGED
|
@@ -1,9 +1,143 @@
|
|
|
1
|
-
// On-chain revocation helpers.
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
// On-chain revocation helpers (spec 272 PAY-DEL-3). `isRevoked` is the read the x402 rail executor
|
|
2
|
+
// MUST run before settling (off-chain check); the DelegationManager ALSO enforces revocation in
|
|
3
|
+
// `redeemDelegation` (on-chain), so revocation is checked twice and is never off-chain-only.
|
|
4
|
+
import { createPublicClient, http, encodeFunctionData, recoverAddress } from 'viem';
|
|
5
|
+
const IS_REVOKED_ABI = [
|
|
6
|
+
{
|
|
7
|
+
type: 'function',
|
|
8
|
+
name: 'isRevoked',
|
|
9
|
+
stateMutability: 'view',
|
|
10
|
+
inputs: [{ name: 'delegationHash', type: 'bytes32' }],
|
|
11
|
+
outputs: [{ type: 'bool' }],
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
// spec 270 v4 — the one connection-agnostic signature surface (ERC-1271 / ERC-6492 / ECDSA).
|
|
15
|
+
const UNIVERSAL_SIG_VALIDATOR_ABI = [
|
|
16
|
+
{
|
|
17
|
+
type: 'function',
|
|
18
|
+
name: 'isValidSig',
|
|
19
|
+
stateMutability: 'view',
|
|
20
|
+
inputs: [
|
|
21
|
+
{ name: 'signer', type: 'address' },
|
|
22
|
+
{ name: 'hash', type: 'bytes32' },
|
|
23
|
+
{ name: 'sig', type: 'bytes' },
|
|
24
|
+
],
|
|
25
|
+
outputs: [{ name: '', type: 'bool' }],
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Validate a signature by `signer` over `digest`, connection-agnostically
|
|
30
|
+
* (spec 270 v4 / spec 287 §7). The verification primitive is selected by the
|
|
31
|
+
* signer's TYPE — a deterministic branch on whether the signer has code, NOT a
|
|
32
|
+
* try-strong-catch-weak fallback (ADR-0013):
|
|
33
|
+
* - **EOA** (no code) → local ECDSA `recoverAddress` (the deployed
|
|
34
|
+
* `UniversalSignatureValidator` reverts on bare EOAs, and a session-key
|
|
35
|
+
* delegate is typically an EOA — same local-recover path `token.ts` uses for
|
|
36
|
+
* the token's own session-key signature).
|
|
37
|
+
* - **Contract** (has code) → on-chain `UniversalSignatureValidator.isValidSig`
|
|
38
|
+
* (ERC-1271 deployed / ERC-6492 counterfactual) via one `eth_call`.
|
|
39
|
+
*
|
|
40
|
+
* Reusable signature surface (spec 287 injects this as the invocation-proof
|
|
41
|
+
* verifier). `readContract` only — no log scans (ADR-0012). Returns `false` on a
|
|
42
|
+
* recover/RPC error rather than throwing, so callers fail closed cleanly.
|
|
43
|
+
*/
|
|
44
|
+
export async function verifyUniversalSignature(args) {
|
|
45
|
+
const client = createPublicClient({ transport: http(args.rpcUrl) });
|
|
46
|
+
let code;
|
|
47
|
+
try {
|
|
48
|
+
code = await client.getCode({ address: args.signer });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const isContract = !!code && code !== '0x' && code.length > 2;
|
|
54
|
+
if (!isContract) {
|
|
55
|
+
// EOA signer → local ECDSA recovery.
|
|
56
|
+
try {
|
|
57
|
+
const recovered = await recoverAddress({ hash: args.digest, signature: args.signature });
|
|
58
|
+
return recovered.toLowerCase() === args.signer.toLowerCase();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Contract signer → ERC-1271 / ERC-6492 via the on-chain validator.
|
|
65
|
+
try {
|
|
66
|
+
return (await client.readContract({
|
|
67
|
+
address: args.universalSignatureValidator,
|
|
68
|
+
abi: UNIVERSAL_SIG_VALIDATOR_ABI,
|
|
69
|
+
functionName: 'isValidSig',
|
|
70
|
+
args: [args.signer, args.digest, args.signature],
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
5
76
|
}
|
|
6
|
-
|
|
7
|
-
|
|
77
|
+
// Matches IDelegationManager.Delegation / Caveat (enforcer, terms, args).
|
|
78
|
+
const REVOKE_BY_OWNER_ABI = [
|
|
79
|
+
{
|
|
80
|
+
type: 'function',
|
|
81
|
+
name: 'revokeDelegationByOwner',
|
|
82
|
+
stateMutability: 'nonpayable',
|
|
83
|
+
inputs: [
|
|
84
|
+
{
|
|
85
|
+
name: 'delegation',
|
|
86
|
+
type: 'tuple',
|
|
87
|
+
components: [
|
|
88
|
+
{ name: 'delegator', type: 'address' },
|
|
89
|
+
{ name: 'delegate', type: 'address' },
|
|
90
|
+
{ name: 'authority', type: 'bytes32' },
|
|
91
|
+
{
|
|
92
|
+
name: 'caveats',
|
|
93
|
+
type: 'tuple[]',
|
|
94
|
+
components: [
|
|
95
|
+
{ name: 'enforcer', type: 'address' },
|
|
96
|
+
{ name: 'terms', type: 'bytes' },
|
|
97
|
+
{ name: 'args', type: 'bytes' },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{ name: 'salt', type: 'uint256' },
|
|
101
|
+
{ name: 'signature', type: 'bytes' },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
outputs: [],
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
/** Is this delegation hash revoked on-chain? The canonical, single mechanism (ADR-0013): reads the
|
|
109
|
+
* DelegationManager's `_revoked` map. Returns `false` if absent — never escalates to a second path. */
|
|
110
|
+
export async function isRevoked(hash, opts) {
|
|
111
|
+
const client = createPublicClient({ transport: http(opts.rpcUrl) });
|
|
112
|
+
return (await client.readContract({
|
|
113
|
+
address: opts.delegationManager,
|
|
114
|
+
abi: IS_REVOKED_ABI,
|
|
115
|
+
functionName: 'isRevoked',
|
|
116
|
+
args: [hash],
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Build the call that revokes a delegation on-chain: `DelegationManager.revokeDelegationByOwner(d)`.
|
|
121
|
+
* The caller (the delegator OR the delegate) submits this through their Smart Account's `execute`
|
|
122
|
+
* (this package owns delegation semantics, not tx/UserOp submission — agent-account/app layer does).
|
|
123
|
+
* Once mined, `isRevoked(hash)` is true and `redeemDelegation` reverts. The on-chain function
|
|
124
|
+
* re-verifies the delegation's signature, so a forged hash cannot be marked revoked.
|
|
125
|
+
*/
|
|
126
|
+
export function buildRevokeDelegationCall(delegation, delegationManager) {
|
|
127
|
+
const data = encodeFunctionData({
|
|
128
|
+
abi: REVOKE_BY_OWNER_ABI,
|
|
129
|
+
functionName: 'revokeDelegationByOwner',
|
|
130
|
+
args: [
|
|
131
|
+
{
|
|
132
|
+
delegator: delegation.delegator,
|
|
133
|
+
delegate: delegation.delegate,
|
|
134
|
+
authority: delegation.authority,
|
|
135
|
+
caveats: delegation.caveats.map((c) => ({ enforcer: c.enforcer, terms: c.terms, args: c.args ?? '0x' })),
|
|
136
|
+
salt: delegation.salt,
|
|
137
|
+
signature: delegation.signature,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
});
|
|
141
|
+
return { to: delegationManager, value: 0n, data };
|
|
8
142
|
}
|
|
9
143
|
//# sourceMappingURL=onchain.js.map
|
package/dist/onchain.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onchain.js","sourceRoot":"","sources":["../src/onchain.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"onchain.js","sourceRoot":"","sources":["../src/onchain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Address, Delegation, Hex } from './types.js';
|
|
2
|
+
import { type EnforcerAddresses, type MandateDecision, type SubsetHandlers } from './mandate.js';
|
|
3
|
+
import type { MethodAuthorizationChecks } from './method-authorization.js';
|
|
4
|
+
/** ES256 over a MESSAGE (hash inside), raw r||s low-S — key-custody's `JwsSignerPort`, structurally. `context` is the bound
|
|
5
|
+
* evidence this release minted for the signature (a key-service key refuses without it; a local key ignores it). */
|
|
6
|
+
export interface DeviceSignerLike {
|
|
7
|
+
sign(message: Uint8Array, context?: {
|
|
8
|
+
evidenceToken: string;
|
|
9
|
+
audience: string;
|
|
10
|
+
}): Promise<Uint8Array>;
|
|
11
|
+
}
|
|
12
|
+
/** WHAT THE RELEASE JUDGED, as facts a key service can hold the signature to (faithkms ADR-0012): the digest the key will
|
|
13
|
+
* sign, the venue (the audience the challenge is bound to), the predicate program, and the actor the release acted for. */
|
|
14
|
+
export interface BoundEvidenceFactsV1 {
|
|
15
|
+
digest: Hex;
|
|
16
|
+
venue: string;
|
|
17
|
+
predicateDigest: Hex;
|
|
18
|
+
subject: Address;
|
|
19
|
+
}
|
|
20
|
+
/** The claims a key service reads off the evidence statement — its wire names. */
|
|
21
|
+
export declare const boundEvidenceClaims: (f: BoundEvidenceFactsV1) => {
|
|
22
|
+
digest: Hex;
|
|
23
|
+
venue: string;
|
|
24
|
+
predicate_digest: Hex;
|
|
25
|
+
};
|
|
26
|
+
/** Mints the evidence statement for ONE judged signature — the release calls it after `allow`, never before. */
|
|
27
|
+
export type BoundEvidencePort = (facts: BoundEvidenceFactsV1) => Promise<{
|
|
28
|
+
evidenceToken: string;
|
|
29
|
+
audience: string;
|
|
30
|
+
}>;
|
|
31
|
+
/** A `BoundEvidencePort` over key-custody's `createEs256EvidenceMinter` (structurally: anything that `mint(subject, claims)`). */
|
|
32
|
+
export declare const boundEvidenceFrom: (minter: {
|
|
33
|
+
mint(subject: string, claims: Record<string, string>): Promise<string>;
|
|
34
|
+
}) => BoundEvidencePort;
|
|
35
|
+
/** THE REASON a presentation mandate is bound to: the statement the person agreed her agent may prove. One intent per
|
|
36
|
+
* (audience, predicate program, issuer facet); every challenge under it is the same reason, which is what makes the
|
|
37
|
+
* wire standing within its window rather than a signature per nonce. */
|
|
38
|
+
export interface PresentationIntentV1 {
|
|
39
|
+
type: 'PresentationIntentV1';
|
|
40
|
+
audience: string;
|
|
41
|
+
predicateDigest: Hex;
|
|
42
|
+
issuerKeyId: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const presentationIntent: (i: {
|
|
45
|
+
audience: string;
|
|
46
|
+
predicateDigest: Hex;
|
|
47
|
+
issuerKeyId: string;
|
|
48
|
+
}) => PresentationIntentV1;
|
|
49
|
+
/** An audience-bound challenge: `<scheme>:<audience>:<nonce>`. The audience is everything between the first and the
|
|
50
|
+
* last colon, so a URL audience with its own colon survives; the nonce never contains one. */
|
|
51
|
+
export declare function parseAudienceBoundChallenge(message: Uint8Array): {
|
|
52
|
+
scheme: string;
|
|
53
|
+
audience: string;
|
|
54
|
+
nonce: string;
|
|
55
|
+
} | null;
|
|
56
|
+
export type PresentationRefusalCode = 'mandate-denied' | 'challenge-unbound' | 'audience-mismatch' | 'approval-required';
|
|
57
|
+
export declare class PresentationReleaseRefused extends Error {
|
|
58
|
+
readonly code: PresentationRefusalCode;
|
|
59
|
+
readonly decision?: MandateDecision | undefined;
|
|
60
|
+
constructor(code: PresentationRefusalCode, message: string, decision?: MandateDecision | undefined);
|
|
61
|
+
}
|
|
62
|
+
export interface PresentationReleaseInput {
|
|
63
|
+
/** The mandate presented for THIS statement — a child derived from her standing wire (`deriveFromStanding`). */
|
|
64
|
+
mandate: Delegation;
|
|
65
|
+
/** The party asking: must be the mandate's delegate (the runtime's key). */
|
|
66
|
+
actor: Address;
|
|
67
|
+
enforcers: EnforcerAddresses;
|
|
68
|
+
checks: MethodAuthorizationChecks;
|
|
69
|
+
/** Injected clock, read per signature. */
|
|
70
|
+
now: () => number;
|
|
71
|
+
/** The custodied device key. */
|
|
72
|
+
signer: DeviceSignerLike;
|
|
73
|
+
/** The release's attestation of what it judged, handed to the key with each signature (required by a key-service key). */
|
|
74
|
+
evidence?: BoundEvidencePort;
|
|
75
|
+
handlers?: SubsetHandlers;
|
|
76
|
+
/** Every decision, allow or deny, with its evidence — the receipt's raw material. */
|
|
77
|
+
onDecision?: (d: {
|
|
78
|
+
step: PresentationStepV1;
|
|
79
|
+
decision: MandateDecision;
|
|
80
|
+
}) => void;
|
|
81
|
+
}
|
|
82
|
+
export interface PresentationStepV1 {
|
|
83
|
+
audience: string;
|
|
84
|
+
predicateDigest: Hex;
|
|
85
|
+
issuerKeyId: string;
|
|
86
|
+
}
|
|
87
|
+
export interface PresentationRelease {
|
|
88
|
+
/** Sign `message` for `step`, or refuse. `message` MUST be an audience-bound challenge whose audience is the step's. */
|
|
89
|
+
sign(step: PresentationStepV1, message: Uint8Array): Promise<Uint8Array>;
|
|
90
|
+
/** The judgement without the signature — for a dry run or a surface that previews what a wire allows. */
|
|
91
|
+
judge(step: PresentationStepV1): Promise<MandateDecision>;
|
|
92
|
+
}
|
|
93
|
+
export declare function createPresentationRelease(input: PresentationReleaseInput): PresentationRelease;
|
|
94
|
+
//# sourceMappingURL=presentation-release.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation-release.d.ts","sourceRoot":"","sources":["../src/presentation-release.ts"],"names":[],"mappings":"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"}
|