@vantic/sdk 0.1.0

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.
Files changed (59) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +42 -0
  3. package/dist/adapters.d.ts +66 -0
  4. package/dist/adapters.d.ts.map +1 -0
  5. package/dist/adapters.js +67 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/credential.d.ts +51 -0
  8. package/dist/credential.d.ts.map +1 -0
  9. package/dist/credential.js +78 -0
  10. package/dist/credential.js.map +1 -0
  11. package/dist/crypto.d.ts +27 -0
  12. package/dist/crypto.d.ts.map +1 -0
  13. package/dist/crypto.js +103 -0
  14. package/dist/crypto.js.map +1 -0
  15. package/dist/did.d.ts +54 -0
  16. package/dist/did.d.ts.map +1 -0
  17. package/dist/did.js +152 -0
  18. package/dist/did.js.map +1 -0
  19. package/dist/envelope.d.ts +23 -0
  20. package/dist/envelope.d.ts.map +1 -0
  21. package/dist/envelope.js +31 -0
  22. package/dist/envelope.js.map +1 -0
  23. package/dist/gate.d.ts +48 -0
  24. package/dist/gate.d.ts.map +1 -0
  25. package/dist/gate.js +46 -0
  26. package/dist/gate.js.map +1 -0
  27. package/dist/guard.d.ts +53 -0
  28. package/dist/guard.d.ts.map +1 -0
  29. package/dist/guard.js +76 -0
  30. package/dist/guard.js.map +1 -0
  31. package/dist/index.d.ts +19 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +19 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/mcp-server.d.ts +23 -0
  36. package/dist/mcp-server.d.ts.map +1 -0
  37. package/dist/mcp-server.js +141 -0
  38. package/dist/mcp-server.js.map +1 -0
  39. package/dist/mcp.d.ts +3 -0
  40. package/dist/mcp.d.ts.map +1 -0
  41. package/dist/mcp.js +5 -0
  42. package/dist/mcp.js.map +1 -0
  43. package/dist/receipt.d.ts +24 -0
  44. package/dist/receipt.d.ts.map +1 -0
  45. package/dist/receipt.js +41 -0
  46. package/dist/receipt.js.map +1 -0
  47. package/dist/revocation.d.ts +23 -0
  48. package/dist/revocation.d.ts.map +1 -0
  49. package/dist/revocation.js +30 -0
  50. package/dist/revocation.js.map +1 -0
  51. package/dist/types.d.ts +98 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +6 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/verify.d.ts +24 -0
  56. package/dist/verify.d.ts.map +1 -0
  57. package/dist/verify.js +124 -0
  58. package/dist/verify.js.map +1 -0
  59. package/package.json +39 -0
package/dist/crypto.js ADDED
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Cryptographic primitives for Vantic. Ed25519 + SHA-256 + canonical JSON.
3
+ * Zero external dependencies — uses Node's built-in `node:crypto`.
4
+ */
5
+ import * as crypto from "node:crypto";
6
+ import { didKeyFromRaw, identifierToJwkX } from "./did.js";
7
+ /** Generate a fresh Ed25519 keypair with both a `key:<x>` id and its `did:key` form. */
8
+ export function generateKeyPair() {
9
+ const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519");
10
+ const jwk = publicKey.export({ format: "jwk" });
11
+ if (!jwk.x)
12
+ throw new Error("failed to derive public key");
13
+ const raw = Buffer.from(jwk.x, "base64url");
14
+ return {
15
+ publicKey: `key:${jwk.x}`,
16
+ did: didKeyFromRaw(raw),
17
+ privateKeyPem: privateKey.export({ format: "pem", type: "pkcs8" }).toString(),
18
+ };
19
+ }
20
+ /** Resolve any supported identifier (`key:<x>` or `did:key:z...`) to a public KeyObject. */
21
+ function publicKeyObjectFromId(identifier) {
22
+ const x = identifierToJwkX(identifier); // handles both key: and did:key:
23
+ return crypto.createPublicKey({
24
+ key: { kty: "OKP", crv: "Ed25519", x },
25
+ format: "jwk",
26
+ });
27
+ }
28
+ /** Sign bytes with a PKCS#8 PEM Ed25519 private key; returns base64url. */
29
+ export function signBytes(privateKeyPem, data) {
30
+ const key = crypto.createPrivateKey(privateKeyPem);
31
+ // For Ed25519 the digest algorithm argument must be null.
32
+ return crypto.sign(null, data, key).toString("base64url");
33
+ }
34
+ /** Verify a base64url Ed25519 signature against a `key:<x>` id. Never throws. */
35
+ export function verifyBytes(keyId, data, signatureB64url) {
36
+ try {
37
+ const key = publicKeyObjectFromId(keyId);
38
+ return crypto.verify(null, data, key, Buffer.from(signatureB64url, "base64url"));
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ /** SHA-256, hex-encoded. */
45
+ export function sha256Hex(data) {
46
+ return crypto.createHash("sha256").update(data).digest("hex");
47
+ }
48
+ /** A UUID for envelope/receipt ids. */
49
+ export function newId() {
50
+ return crypto.randomUUID();
51
+ }
52
+ /**
53
+ * Canonical JSON serialization (JCS-compatible subset, RFC 8785 target):
54
+ * object keys sorted lexicographically, no insignificant whitespace, UTF-8.
55
+ * Amounts are integers by protocol rule (§4.1), so number formatting is unambiguous.
56
+ */
57
+ export function canonicalize(value) {
58
+ if (value === null)
59
+ return "null";
60
+ const t = typeof value;
61
+ if (t === "number") {
62
+ if (!Number.isFinite(value))
63
+ throw new Error("non-finite number cannot be canonicalized");
64
+ return JSON.stringify(value);
65
+ }
66
+ if (t === "boolean")
67
+ return value ? "true" : "false";
68
+ if (t === "string")
69
+ return JSON.stringify(value);
70
+ if (t === "undefined")
71
+ throw new Error("undefined cannot be canonicalized");
72
+ if (Array.isArray(value))
73
+ return `[${value.map(canonicalize).join(",")}]`;
74
+ if (t === "object") {
75
+ const obj = value;
76
+ const keys = Object.keys(obj)
77
+ .filter((k) => obj[k] !== undefined)
78
+ .sort();
79
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalize(obj[k])}`).join(",")}}`;
80
+ }
81
+ throw new Error(`unsupported type in canonicalize: ${t}`);
82
+ }
83
+ /**
84
+ * Produce a Signature over an object, excluding any existing `signature` field.
85
+ * Used to sign both envelopes (by principal) and receipts (by agent).
86
+ */
87
+ export function signObject(obj, by, privateKeyPem) {
88
+ const { signature: _drop, ...unsigned } = obj;
89
+ const bytes = Buffer.from(canonicalize(unsigned), "utf8");
90
+ return { alg: "Ed25519", by, value: signBytes(privateKeyPem, bytes) };
91
+ }
92
+ /** Verify an object's embedded Signature was produced by `expectedSigner`. */
93
+ export function verifyObjectSignature(obj, expectedSigner) {
94
+ const sig = obj.signature;
95
+ if (!sig || sig.alg !== "Ed25519")
96
+ return false;
97
+ if (sig.by !== expectedSigner)
98
+ return false;
99
+ const { signature: _drop, ...unsigned } = obj;
100
+ const bytes = Buffer.from(canonicalize(unsigned), "utf8");
101
+ return verifyBytes(sig.by, bytes, sig.value);
102
+ }
103
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
package/dist/did.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Decentralized Identifiers (DIDs) for Vantic — W3C `did:key` (self-contained) and
3
+ * `did:web` scaffolding. This upgrades a principal/agent identifier from "a bare public
4
+ * key" to "a resolvable, standard, verifiable identity" without changing the protocol:
5
+ * envelopes and receipts can use either `key:<x>` or `did:key:z...` identifiers, and the
6
+ * crypto layer resolves both to the same Ed25519 key.
7
+ *
8
+ * Zero dependencies: base58btc + multicodec implemented inline.
9
+ */
10
+ import type { KeyId } from "./types.js";
11
+ export declare function base58Encode(bytes: Uint8Array): string;
12
+ export declare function base58Decode(str: string): Uint8Array;
13
+ /** Multibase key fragment, e.g. "z6Mk..." — the part after `did:key:` and after `#`. */
14
+ export declare function multibaseFromRaw(raw: Buffer): string;
15
+ /** Raw 32-byte Ed25519 public key from a `z...` multibase string. */
16
+ export declare function rawFromMultibase(multibase: string): Buffer;
17
+ export declare function didKeyFromRaw(raw: Buffer): string;
18
+ export declare function rawFromDidKey(did: string): Buffer;
19
+ export declare function isDidKey(id: string): boolean;
20
+ export declare function isKeyId(id: string): boolean;
21
+ export declare function isDid(id: string): boolean;
22
+ /** Raw Ed25519 public key bytes from any supported identifier. */
23
+ export declare function identifierToRaw(identifier: KeyId): Buffer;
24
+ /** JWK `x` (base64url raw public key) from any supported identifier — used by the crypto layer. */
25
+ export declare function identifierToJwkX(identifier: KeyId): string;
26
+ export declare function keyIdFromRaw(raw: Buffer): KeyId;
27
+ /** Convert between the two identifier forms for the same key. */
28
+ export declare function keyIdToDidKey(keyId: KeyId): string;
29
+ export declare function didKeyToKeyId(did: string): KeyId;
30
+ export interface VerificationMethod {
31
+ id: string;
32
+ type: "Ed25519VerificationKey2020";
33
+ controller: string;
34
+ publicKeyMultibase: string;
35
+ }
36
+ export interface DIDDocument {
37
+ "@context": string[];
38
+ id: string;
39
+ verificationMethod: VerificationMethod[];
40
+ authentication: string[];
41
+ assertionMethod: string[];
42
+ }
43
+ /** Resolve a did:key to its DID Document synchronously (the key IS the document). */
44
+ export declare function resolveDidKey(did: string): DIDDocument;
45
+ /** Map a did:web identifier to the URL of its DID document. */
46
+ export declare function didWebToUrl(did: string): string;
47
+ /** Build a publishable did:web DID Document for a raw Ed25519 key (host it at the URL above). */
48
+ export declare function buildDidWebDocument(did: string, raw: Buffer): DIDDocument;
49
+ /** A DID resolver: did:key is handled synchronously; did:web is delegated to `fetchJson`. */
50
+ export interface DidResolver {
51
+ resolve(did: string): Promise<DIDDocument>;
52
+ }
53
+ export declare function createResolver(fetchJson?: (url: string) => Promise<unknown>): DidResolver;
54
+ //# sourceMappingURL=did.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAKxC,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAkBtD;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAiBpD;AAKD,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGjD;AAGD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE5C;AACD,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE3C;AACD,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEzC;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,UAAU,EAAE,KAAK,GAAG,MAAM,CAIzD;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,KAAK,GAAG,MAAM,CAE1D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAE/C;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAElD;AACD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAEhD;AAGD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,4BAA4B,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AACD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAWtD;AAGD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS/C;AAED,iGAAiG;AACjG,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAUzE;AAED,6FAA6F;AAC7F,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC5C;AAED,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,WAAW,CAWzF"}
package/dist/did.js ADDED
@@ -0,0 +1,152 @@
1
+ // ── base58btc (Bitcoin alphabet) ────────────────────────────────────────────────────────
2
+ const B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
3
+ export function base58Encode(bytes) {
4
+ const digits = [];
5
+ for (const byte of bytes) {
6
+ let carry = byte;
7
+ for (let i = 0; i < digits.length; i++) {
8
+ carry += digits[i] << 8;
9
+ digits[i] = carry % 58;
10
+ carry = (carry / 58) | 0;
11
+ }
12
+ while (carry > 0) {
13
+ digits.push(carry % 58);
14
+ carry = (carry / 58) | 0;
15
+ }
16
+ }
17
+ let out = "";
18
+ for (let i = 0; i < bytes.length && bytes[i] === 0; i++)
19
+ out += B58[0];
20
+ for (let i = digits.length - 1; i >= 0; i--)
21
+ out += B58[digits[i]];
22
+ return out;
23
+ }
24
+ export function base58Decode(str) {
25
+ const bytes = [];
26
+ for (const ch of str) {
27
+ let carry = B58.indexOf(ch);
28
+ if (carry < 0)
29
+ throw new Error(`invalid base58 character: ${ch}`);
30
+ for (let i = 0; i < bytes.length; i++) {
31
+ carry += bytes[i] * 58;
32
+ bytes[i] = carry & 0xff;
33
+ carry >>= 8;
34
+ }
35
+ while (carry > 0) {
36
+ bytes.push(carry & 0xff);
37
+ carry >>= 8;
38
+ }
39
+ }
40
+ for (let i = 0; i < str.length && str[i] === B58[0]; i++)
41
+ bytes.push(0);
42
+ return Uint8Array.from(bytes.reverse());
43
+ }
44
+ // ── did:key for Ed25519 (multicodec 0xed01) ──────────────────────────────────────────────
45
+ const ED25519_MULTICODEC = Uint8Array.from([0xed, 0x01]);
46
+ /** Multibase key fragment, e.g. "z6Mk..." — the part after `did:key:` and after `#`. */
47
+ export function multibaseFromRaw(raw) {
48
+ const prefixed = Buffer.concat([Buffer.from(ED25519_MULTICODEC), raw]);
49
+ return "z" + base58Encode(prefixed);
50
+ }
51
+ /** Raw 32-byte Ed25519 public key from a `z...` multibase string. */
52
+ export function rawFromMultibase(multibase) {
53
+ if (!multibase.startsWith("z"))
54
+ throw new Error("unsupported multibase (expected base58btc 'z')");
55
+ const decoded = base58Decode(multibase.slice(1));
56
+ if (decoded[0] !== 0xed || decoded[1] !== 0x01)
57
+ throw new Error("not an Ed25519 multicodec key");
58
+ return Buffer.from(decoded.slice(2));
59
+ }
60
+ export function didKeyFromRaw(raw) {
61
+ return `did:key:${multibaseFromRaw(raw)}`;
62
+ }
63
+ export function rawFromDidKey(did) {
64
+ if (!did.startsWith("did:key:"))
65
+ throw new Error("not a did:key");
66
+ return rawFromMultibase(did.slice("did:key:".length));
67
+ }
68
+ // ── Identifier helpers (support `key:<x>` and `did:key:z...`) ─────────────────────────────
69
+ export function isDidKey(id) {
70
+ return id.startsWith("did:key:");
71
+ }
72
+ export function isKeyId(id) {
73
+ return id.startsWith("key:");
74
+ }
75
+ export function isDid(id) {
76
+ return id.startsWith("did:");
77
+ }
78
+ /** Raw Ed25519 public key bytes from any supported identifier. */
79
+ export function identifierToRaw(identifier) {
80
+ if (isKeyId(identifier))
81
+ return Buffer.from(identifier.slice("key:".length), "base64url");
82
+ if (isDidKey(identifier))
83
+ return rawFromDidKey(identifier);
84
+ throw new Error(`unsupported identifier (expected key: or did:key:): ${identifier}`);
85
+ }
86
+ /** JWK `x` (base64url raw public key) from any supported identifier — used by the crypto layer. */
87
+ export function identifierToJwkX(identifier) {
88
+ return identifierToRaw(identifier).toString("base64url");
89
+ }
90
+ export function keyIdFromRaw(raw) {
91
+ return `key:${raw.toString("base64url")}`;
92
+ }
93
+ /** Convert between the two identifier forms for the same key. */
94
+ export function keyIdToDidKey(keyId) {
95
+ return didKeyFromRaw(identifierToRaw(keyId));
96
+ }
97
+ export function didKeyToKeyId(did) {
98
+ return keyIdFromRaw(rawFromDidKey(did));
99
+ }
100
+ /** Resolve a did:key to its DID Document synchronously (the key IS the document). */
101
+ export function resolveDidKey(did) {
102
+ const raw = rawFromDidKey(did);
103
+ const mb = multibaseFromRaw(raw);
104
+ const vmId = `${did}#${mb}`;
105
+ return {
106
+ "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"],
107
+ id: did,
108
+ verificationMethod: [{ id: vmId, type: "Ed25519VerificationKey2020", controller: did, publicKeyMultibase: mb }],
109
+ authentication: [vmId],
110
+ assertionMethod: [vmId],
111
+ };
112
+ }
113
+ // ── did:web scaffolding (resolution needs an HTTP fetch, injected by the caller) ──────────
114
+ /** Map a did:web identifier to the URL of its DID document. */
115
+ export function didWebToUrl(did) {
116
+ if (!did.startsWith("did:web:"))
117
+ throw new Error("not a did:web");
118
+ const rest = did.slice("did:web:".length);
119
+ const parts = rest.split(":").map(decodeURIComponent);
120
+ const host = parts[0];
121
+ const path = parts.slice(1);
122
+ return path.length === 0
123
+ ? `https://${host}/.well-known/did.json`
124
+ : `https://${host}/${path.join("/")}/did.json`;
125
+ }
126
+ /** Build a publishable did:web DID Document for a raw Ed25519 key (host it at the URL above). */
127
+ export function buildDidWebDocument(did, raw) {
128
+ const mb = multibaseFromRaw(raw);
129
+ const vmId = `${did}#owner`;
130
+ return {
131
+ "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/ed25519-2020/v1"],
132
+ id: did,
133
+ verificationMethod: [{ id: vmId, type: "Ed25519VerificationKey2020", controller: did, publicKeyMultibase: mb }],
134
+ authentication: [vmId],
135
+ assertionMethod: [vmId],
136
+ };
137
+ }
138
+ export function createResolver(fetchJson) {
139
+ return {
140
+ async resolve(did) {
141
+ if (isDidKey(did))
142
+ return resolveDidKey(did);
143
+ if (did.startsWith("did:web:")) {
144
+ if (!fetchJson)
145
+ throw new Error("did:web resolution requires a fetchJson implementation");
146
+ return (await fetchJson(didWebToUrl(did)));
147
+ }
148
+ throw new Error(`unsupported DID method: ${did}`);
149
+ },
150
+ };
151
+ }
152
+ //# sourceMappingURL=did.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"did.js","sourceRoot":"","sources":["../src/did.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { type Mandate, type KeyId, type Scope } from "./types.js";
2
+ export interface IssueMandateParams {
3
+ /** Agent being authorized (its public key id). */
4
+ agent: KeyId;
5
+ /** Principal granting authority (its public key id). */
6
+ principal: KeyId;
7
+ /** Principal's PKCS#8 PEM private key — signs the envelope. */
8
+ principalPrivateKeyPem: string;
9
+ scope: Scope;
10
+ /** Mandate lifetime in seconds from `now`. */
11
+ ttlSeconds: number;
12
+ /** Optional revocation endpoint the verifier may consult. */
13
+ revocationUrl?: string;
14
+ /** Override the clock (testing/determinism). */
15
+ now?: Date;
16
+ }
17
+ /** Create and sign a delegation envelope. */
18
+ export declare function issueMandate(params: IssueMandateParams): Mandate;
19
+ /** Verify the envelope's signature is a valid Ed25519 signature by its `principal`. */
20
+ export declare function verifyMandateSignature(env: Mandate): boolean;
21
+ /** SHA-256 (hex) of the canonical signed envelope. Binds receipts to this exact mandate. */
22
+ export declare function mandateHash(env: Mandate): string;
23
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,kDAAkD;IAClD,KAAK,EAAE,KAAK,CAAC;IACb,wDAAwD;IACxD,SAAS,EAAE,KAAK,CAAC;IACjB,+DAA+D;IAC/D,sBAAsB,EAAE,MAAM,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;IACb,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAchE;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Delegation Mandate: a signed mandate from a principal to an agent.
3
+ * See spec §4.
4
+ */
5
+ import { canonicalize, newId, sha256Hex, signObject, verifyObjectSignature } from "./crypto.js";
6
+ import { MANDATE_VERSION } from "./types.js";
7
+ /** Create and sign a delegation envelope. */
8
+ export function issueMandate(params) {
9
+ const now = params.now ?? new Date();
10
+ const base = {
11
+ version: MANDATE_VERSION,
12
+ id: newId(),
13
+ agent: params.agent,
14
+ principal: params.principal,
15
+ issuedAt: now.toISOString(),
16
+ expiresAt: new Date(now.getTime() + params.ttlSeconds * 1000).toISOString(),
17
+ scope: params.scope,
18
+ ...(params.revocationUrl ? { revocation: { url: params.revocationUrl } } : {}),
19
+ };
20
+ const signature = signObject(base, params.principal, params.principalPrivateKeyPem);
21
+ return { ...base, signature };
22
+ }
23
+ /** Verify the envelope's signature is a valid Ed25519 signature by its `principal`. */
24
+ export function verifyMandateSignature(env) {
25
+ return verifyObjectSignature(env, env.principal);
26
+ }
27
+ /** SHA-256 (hex) of the canonical signed envelope. Binds receipts to this exact mandate. */
28
+ export function mandateHash(env) {
29
+ return sha256Hex(canonicalize(env));
30
+ }
31
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,eAAe,EAAwC,MAAM,YAAY,CAAC;AAkBnF,6CAA6C;AAC7C,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAAY;QACpB,OAAO,EAAE,eAAe;QACxB,EAAE,EAAE,KAAK,EAAE;QACX,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE;QAC3B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;QAC3E,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/E,CAAC;IACF,MAAM,SAAS,GAAG,UAAU,CAAC,IAA0C,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAC1H,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,sBAAsB,CAAC,GAAY;IACjD,OAAO,qBAAqB,CAAC,GAAyC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AACzF,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;AACtC,CAAC"}
package/dist/gate.d.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Gate — the counterparty side.
3
+ *
4
+ * The client-side guard (AgentWallet) protects an agent from itself. This is the other
5
+ * half: a resource server, merchant, paid API, or another agent uses `checkMandate` to
6
+ * REQUIRE a valid mandate before dealing with an incoming agent — verifying that the
7
+ * agent's mandate is signed by a real principal and authorizes a payment to *this*
8
+ * counterparty, within its limits and remaining budget.
9
+ *
10
+ * This is what makes a mandate something a counterparty *requires* rather than a
11
+ * DIY-able self-check: the requirement lives on the receiving side, so an agent can only
12
+ * transact here by presenting the verifiable artifact. Nothing an agent codes on its own
13
+ * side satisfies a counterparty that demands a signed mandate.
14
+ */
15
+ import { type VerifyOptions } from "./verify.js";
16
+ import type { Mandate, Receipt } from "./types.js";
17
+ export interface ResourceRequirement {
18
+ /** This counterparty's identifier (the resource/merchant/agent being paid). */
19
+ counterparty: string;
20
+ /** Required action type, e.g. "purchase" | "subscribe" | "pay-per-use". */
21
+ action: string;
22
+ /** Price the mandate must authorize, in minor units of `currency`. */
23
+ amount: number;
24
+ currency: string;
25
+ }
26
+ export interface GateResult {
27
+ /** True iff the presented mandate authorizes this payment to this counterparty. */
28
+ granted: boolean;
29
+ /** Human-readable failure reasons; empty iff granted. */
30
+ reasons: string[];
31
+ /** The principal (sponsor) that signed the mandate — present iff the signature is valid. */
32
+ principal?: string;
33
+ /** The agent the mandate authorizes. */
34
+ agent: string;
35
+ }
36
+ /**
37
+ * Does `envelope` (plus any prior receipts under it) authorize a payment matching
38
+ * `requirement` to THIS counterparty? Verifies the mandate's signature, validity window,
39
+ * revocation, scope (this counterparty + action + per-transaction cap), and remaining
40
+ * budget. Returns granted + reasons, plus the verified principal/agent for KYA.
41
+ *
42
+ * Budget caveat: the rolling-budget check is only sound if `priorReceipts` is the agent's
43
+ * COMPLETE spend history under this mandate. An isolated counterparty that passes a partial or
44
+ * empty history is soundly enforcing the per-transaction cap + scope (which don't need history),
45
+ * but NOT the global rolling budget — the agent controls which receipts it presents. See spec §8.
46
+ */
47
+ export declare function checkMandate(envelope: Mandate, requirement: ResourceRequirement, priorReceipts?: Receipt[], opts?: VerifyOptions): GateResult;
48
+ //# sourceMappingURL=gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAa,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,EAAU,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,mBAAmB,EAChC,aAAa,GAAE,OAAO,EAAO,EAC7B,IAAI,GAAE,aAAkB,GACvB,UAAU,CAiBZ"}
package/dist/gate.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Gate — the counterparty side.
3
+ *
4
+ * The client-side guard (AgentWallet) protects an agent from itself. This is the other
5
+ * half: a resource server, merchant, paid API, or another agent uses `checkMandate` to
6
+ * REQUIRE a valid mandate before dealing with an incoming agent — verifying that the
7
+ * agent's mandate is signed by a real principal and authorizes a payment to *this*
8
+ * counterparty, within its limits and remaining budget.
9
+ *
10
+ * This is what makes a mandate something a counterparty *requires* rather than a
11
+ * DIY-able self-check: the requirement lives on the receiving side, so an agent can only
12
+ * transact here by presenting the verifiable artifact. Nothing an agent codes on its own
13
+ * side satisfies a counterparty that demands a signed mandate.
14
+ */
15
+ import { authorize } from "./verify.js";
16
+ import { verifyMandateSignature } from "./envelope.js";
17
+ /**
18
+ * Does `envelope` (plus any prior receipts under it) authorize a payment matching
19
+ * `requirement` to THIS counterparty? Verifies the mandate's signature, validity window,
20
+ * revocation, scope (this counterparty + action + per-transaction cap), and remaining
21
+ * budget. Returns granted + reasons, plus the verified principal/agent for KYA.
22
+ *
23
+ * Budget caveat: the rolling-budget check is only sound if `priorReceipts` is the agent's
24
+ * COMPLETE spend history under this mandate. An isolated counterparty that passes a partial or
25
+ * empty history is soundly enforcing the per-transaction cap + scope (which don't need history),
26
+ * but NOT the global rolling budget — the agent controls which receipts it presents. See spec §8.
27
+ */
28
+ export function checkMandate(envelope, requirement, priorReceipts = [], opts = {}) {
29
+ const candidate = {
30
+ type: requirement.action,
31
+ counterparty: requirement.counterparty,
32
+ amount: requirement.amount,
33
+ currency: requirement.currency,
34
+ };
35
+ // `authorize` checks: envelope signature, validity window, revocation, the chain,
36
+ // the candidate's scope (action/counterparty/per-txn cap), and budget incl. candidate.
37
+ const verdict = authorize(envelope, priorReceipts, candidate, opts);
38
+ const sigOk = verifyMandateSignature(envelope);
39
+ return {
40
+ granted: verdict.ok,
41
+ reasons: verdict.reasons,
42
+ ...(sigOk ? { principal: envelope.principal } : {}),
43
+ agent: envelope.agent,
44
+ };
45
+ }
46
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,SAAS,EAAsB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAwBvD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAiB,EACjB,WAAgC,EAChC,gBAA2B,EAAE,EAC7B,OAAsB,EAAE;IAExB,MAAM,SAAS,GAAW;QACxB,IAAI,EAAE,WAAW,CAAC,MAAM;QACxB,YAAY,EAAE,WAAW,CAAC,YAAY;QACtC,MAAM,EAAE,WAAW,CAAC,MAAM;QAC1B,QAAQ,EAAE,WAAW,CAAC,QAAQ;KAC/B,CAAC;IACF,kFAAkF;IAClF,uFAAuF;IACvF,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACpE,MAAM,KAAK,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,EAAE;QACnB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,KAAK,EAAE,QAAQ,CAAC,KAAK;KACtB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,53 @@
1
+ import type { Action, Mandate, Outcome, Receipt, Verdict } from "./types.js";
2
+ /** Thrown when the mandate blocks an action before any money moves. */
3
+ export declare class GuardViolation extends Error {
4
+ readonly reasons: string[];
5
+ readonly action: Action;
6
+ constructor(action: Action, reasons: string[]);
7
+ }
8
+ /**
9
+ * The developer's executor: the real side-effect (charge a card, submit an x402 payment,
10
+ * call a purchase tool). Returns the settled/failed outcome and any result payload.
11
+ * The guard only calls this if the action is authorized.
12
+ */
13
+ export type SpendExecutor<T> = (action: Action) => Promise<{
14
+ outcome: Outcome;
15
+ result?: T;
16
+ }> | {
17
+ outcome: Outcome;
18
+ result?: T;
19
+ };
20
+ export interface AgentWalletOptions {
21
+ /** Override the clock (testing/determinism). */
22
+ now?: () => Date;
23
+ /** Optional sink for signed receipts — e.g. POST them to a hosted verifier (network value). */
24
+ onReceipt?: (receipt: Receipt) => void;
25
+ /** Optional hook fired when an action is blocked (telemetry, alerting). */
26
+ onViolation?: (violation: GuardViolation) => void;
27
+ }
28
+ /**
29
+ * Wraps an envelope + the agent's key and enforces it locally around every spend.
30
+ * Holds the local receipt chain so budgets accumulate correctly across a session.
31
+ */
32
+ export declare class AgentWallet {
33
+ private readonly envelope;
34
+ private readonly agentPrivateKeyPem;
35
+ private readonly options;
36
+ private chain;
37
+ constructor(envelope: Mandate, agentPrivateKeyPem: string, options?: AgentWalletOptions);
38
+ private now;
39
+ /** The signed receipt chain accumulated so far (read-only). */
40
+ get receipts(): readonly Receipt[];
41
+ /** Check whether an action WOULD be allowed, without executing or recording anything. */
42
+ preauthorize(action: Action): Verdict;
43
+ /**
44
+ * The guarded spend. Runs the mandate check FIRST; only if it passes is `executor`
45
+ * invoked (the point at which real money moves). Records a signed receipt for the
46
+ * outcome. Throws GuardViolation — before any side effect — if the action is out of scope.
47
+ */
48
+ spend<T>(action: Action, executor: SpendExecutor<T>): Promise<{
49
+ receipt: Receipt;
50
+ result?: T;
51
+ }>;
52
+ }
53
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7E,uEAAuE;AACvE,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;CAM9C;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAC7B,MAAM,EAAE,MAAM,KACX,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAElF,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,2EAA2E;IAC3E,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAED;;;GAGG;AACH,qBAAa,WAAW;IAGpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,KAAK,CAAiB;gBAEX,QAAQ,EAAE,OAAO,EACjB,kBAAkB,EAAE,MAAM,EAC1B,OAAO,GAAE,kBAAuB;IAGnD,OAAO,CAAC,GAAG;IAIX,+DAA+D;IAC/D,IAAI,QAAQ,IAAI,SAAS,OAAO,EAAE,CAEjC;IAED,yFAAyF;IACzF,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIrC;;;;OAIG;IACG,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,CAAC;CAsBtG"}
package/dist/guard.js ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Guard — a client-side spending firewall around an agent's own money-moving actions.
3
+ *
4
+ * This protects the developer's own agent from itself (bugs, hallucinations, prompt
5
+ * injection). The guard check runs BEFORE the executor, so a compromised agent cannot
6
+ * execute an out-of-scope payment. Every allowed action still emits a signed receipt —
7
+ * a tamper-proof audit trail.
8
+ *
9
+ * A developer installs this because they do not want their agent tricked into wiring funds
10
+ * to an attacker — a documented, actively-exploited failure mode.
11
+ */
12
+ import { authorize } from "./verify.js";
13
+ import { issueReceipt, nextPrevHash } from "./receipt.js";
14
+ /** Thrown when the mandate blocks an action before any money moves. */
15
+ export class GuardViolation extends Error {
16
+ reasons;
17
+ action;
18
+ constructor(action, reasons) {
19
+ super(`mandate blocked action: ${reasons.join("; ")}`);
20
+ this.name = "GuardViolation";
21
+ this.reasons = reasons;
22
+ this.action = action;
23
+ }
24
+ }
25
+ /**
26
+ * Wraps an envelope + the agent's key and enforces it locally around every spend.
27
+ * Holds the local receipt chain so budgets accumulate correctly across a session.
28
+ */
29
+ export class AgentWallet {
30
+ envelope;
31
+ agentPrivateKeyPem;
32
+ options;
33
+ chain = [];
34
+ constructor(envelope, agentPrivateKeyPem, options = {}) {
35
+ this.envelope = envelope;
36
+ this.agentPrivateKeyPem = agentPrivateKeyPem;
37
+ this.options = options;
38
+ }
39
+ now() {
40
+ return this.options.now?.() ?? new Date();
41
+ }
42
+ /** The signed receipt chain accumulated so far (read-only). */
43
+ get receipts() {
44
+ return this.chain;
45
+ }
46
+ /** Check whether an action WOULD be allowed, without executing or recording anything. */
47
+ preauthorize(action) {
48
+ return authorize(this.envelope, this.chain, action, { now: this.now() });
49
+ }
50
+ /**
51
+ * The guarded spend. Runs the mandate check FIRST; only if it passes is `executor`
52
+ * invoked (the point at which real money moves). Records a signed receipt for the
53
+ * outcome. Throws GuardViolation — before any side effect — if the action is out of scope.
54
+ */
55
+ async spend(action, executor) {
56
+ const verdict = this.preauthorize(action);
57
+ if (!verdict.ok) {
58
+ const violation = new GuardViolation(action, verdict.reasons);
59
+ this.options.onViolation?.(violation);
60
+ throw violation; // executor is NEVER called — the firewall property
61
+ }
62
+ const { outcome, result } = await executor(action);
63
+ const receipt = issueReceipt({
64
+ envelope: this.envelope,
65
+ agentPrivateKeyPem: this.agentPrivateKeyPem,
66
+ action,
67
+ prevReceiptHash: nextPrevHash(this.chain),
68
+ outcome,
69
+ now: this.now(),
70
+ });
71
+ this.chain.push(receipt);
72
+ this.options.onReceipt?.(receipt);
73
+ return { receipt, result };
74
+ }
75
+ }
76
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG1D,uEAAuE;AACvE,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,OAAO,CAAW;IAClB,MAAM,CAAS;IACxB,YAAY,MAAc,EAAE,OAAiB;QAC3C,KAAK,CAAC,2BAA2B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAoBD;;;GAGG;AACH,MAAM,OAAO,WAAW;IAGH;IACA;IACA;IAJX,KAAK,GAAc,EAAE,CAAC;IAC9B,YACmB,QAAiB,EACjB,kBAA0B,EAC1B,UAA8B,EAAE;QAFhC,aAAQ,GAAR,QAAQ,CAAS;QACjB,uBAAkB,GAAlB,kBAAkB,CAAQ;QAC1B,YAAO,GAAP,OAAO,CAAyB;IAChD,CAAC;IAEI,GAAG;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,+DAA+D;IAC/D,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,yFAAyF;IACzF,YAAY,CAAC,MAAc;QACzB,OAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAI,MAAc,EAAE,QAA0B;QACvD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,SAAS,GAAG,IAAI,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC9D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,SAAS,CAAC,CAAC,mDAAmD;QACtE,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,YAAY,CAAC;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,MAAM;YACN,eAAe,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;YACzC,OAAO;YACP,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;SAChB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC;CACF"}