@goodmeta/agent-verifier 0.2.0 → 0.6.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 (78) hide show
  1. package/README.md +67 -26
  2. package/dist/ap2/chain.d.ts +43 -0
  3. package/dist/ap2/chain.d.ts.map +1 -0
  4. package/dist/ap2/chain.js +100 -0
  5. package/dist/ap2/chain.js.map +1 -0
  6. package/dist/ap2/chains.d.ts +68 -0
  7. package/dist/ap2/chains.d.ts.map +1 -0
  8. package/dist/ap2/chains.js +119 -0
  9. package/dist/ap2/chains.js.map +1 -0
  10. package/dist/ap2/constraints.d.ts +47 -0
  11. package/dist/ap2/constraints.d.ts.map +1 -0
  12. package/dist/ap2/constraints.js +231 -0
  13. package/dist/ap2/constraints.js.map +1 -0
  14. package/dist/ap2/hash.d.ts +23 -0
  15. package/dist/ap2/hash.d.ts.map +1 -0
  16. package/dist/ap2/hash.js +54 -0
  17. package/dist/ap2/hash.js.map +1 -0
  18. package/dist/ap2/index.d.ts +28 -0
  19. package/dist/ap2/index.d.ts.map +1 -0
  20. package/dist/ap2/index.js +35 -0
  21. package/dist/ap2/index.js.map +1 -0
  22. package/dist/ap2/jwk.d.ts +24 -0
  23. package/dist/ap2/jwk.d.ts.map +1 -0
  24. package/dist/ap2/jwk.js +29 -0
  25. package/dist/ap2/jwk.js.map +1 -0
  26. package/dist/ap2/kb-sd-jwt.d.ts +44 -0
  27. package/dist/ap2/kb-sd-jwt.d.ts.map +1 -0
  28. package/dist/ap2/kb-sd-jwt.js +97 -0
  29. package/dist/ap2/kb-sd-jwt.js.map +1 -0
  30. package/dist/ap2/keys.d.ts +41 -0
  31. package/dist/ap2/keys.d.ts.map +1 -0
  32. package/dist/ap2/keys.js +114 -0
  33. package/dist/ap2/keys.js.map +1 -0
  34. package/dist/ap2/max-flow.d.ts +26 -0
  35. package/dist/ap2/max-flow.d.ts.map +1 -0
  36. package/dist/ap2/max-flow.js +173 -0
  37. package/dist/ap2/max-flow.js.map +1 -0
  38. package/dist/ap2/parse.d.ts +35 -0
  39. package/dist/ap2/parse.d.ts.map +1 -0
  40. package/dist/ap2/parse.js +78 -0
  41. package/dist/ap2/parse.js.map +1 -0
  42. package/dist/ap2/sd-jwt.d.ts +83 -0
  43. package/dist/ap2/sd-jwt.d.ts.map +1 -0
  44. package/dist/ap2/sd-jwt.js +306 -0
  45. package/dist/ap2/sd-jwt.js.map +1 -0
  46. package/dist/ap2/types.d.ts +270 -0
  47. package/dist/ap2/types.d.ts.map +1 -0
  48. package/dist/ap2/types.js +141 -0
  49. package/dist/ap2/types.js.map +1 -0
  50. package/dist/client.d.ts +152 -0
  51. package/dist/client.d.ts.map +1 -0
  52. package/dist/client.js +171 -0
  53. package/dist/client.js.map +1 -0
  54. package/dist/index.d.ts +27 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +30 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/policy.d.ts +45 -0
  59. package/dist/policy.d.ts.map +1 -0
  60. package/dist/policy.js +88 -0
  61. package/dist/policy.js.map +1 -0
  62. package/dist/receipt-jwt.d.ts +30 -0
  63. package/dist/receipt-jwt.d.ts.map +1 -0
  64. package/dist/receipt-jwt.js +39 -0
  65. package/dist/receipt-jwt.js.map +1 -0
  66. package/dist/schema.d.ts +41 -0
  67. package/dist/schema.d.ts.map +1 -0
  68. package/dist/schema.js +50 -0
  69. package/dist/schema.js.map +1 -0
  70. package/dist/types.d.ts +116 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +8 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/verify.d.ts +24 -0
  75. package/dist/verify.d.ts.map +1 -0
  76. package/dist/verify.js +69 -0
  77. package/dist/verify.js.map +1 -0
  78. package/package.json +14 -7
package/dist/policy.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Policy-Based Spending Verification
3
+ *
4
+ * For systems that don't use AP2 mandates (Lago, custom billing, etc).
5
+ * Spending rules are configured via API, not cryptographic signatures.
6
+ *
7
+ * Same core logic: can this agent spend $X on Y right now?
8
+ */
9
+ import { PolicyRequestSchema } from "./schema.js";
10
+ /**
11
+ * Check a spending request against a local policy (stateless).
12
+ * For cross-agent budget tracking, use the hosted Verifier.
13
+ */
14
+ export function checkPolicy(policy, request, currentSpend = 0) {
15
+ // Validate the untrusted request at the boundary. `amount` is coerced to
16
+ // positive integer cents — a negative amount would otherwise pass every ">"
17
+ // check below and then inflate the remaining budget (remaining - (-x)).
18
+ const parsed = PolicyRequestSchema.safeParse(request);
19
+ if (!parsed.success) {
20
+ const issue = parsed.error.issues[0];
21
+ return {
22
+ approved: false,
23
+ reason: issue?.path[0] === "amount" ? "INVALID_AMOUNT" : "INVALID_REQUEST",
24
+ detail: issue?.message ?? "invalid request",
25
+ };
26
+ }
27
+ const { amount, metadata } = parsed.data;
28
+ const { constraints } = policy;
29
+ // Per-event max
30
+ if (amount > constraints.maxPerEvent) {
31
+ return {
32
+ approved: false,
33
+ reason: "AMOUNT_EXCEEDED",
34
+ detail: `$${(amount / 100).toFixed(2)} exceeds per-event max $${(constraints.maxPerEvent / 100).toFixed(2)}`,
35
+ };
36
+ }
37
+ // Budget check
38
+ const remaining = policy.budgetTotal - currentSpend;
39
+ if (amount > remaining) {
40
+ return {
41
+ approved: false,
42
+ reason: "BUDGET_EXCEEDED",
43
+ detail: `$${(amount / 100).toFixed(2)} exceeds remaining budget $${(remaining / 100).toFixed(2)}`,
44
+ remaining: { budget: remaining, period: policy.budgetPeriod },
45
+ };
46
+ }
47
+ // Code allowlist
48
+ if (metadata?.code && constraints.allowedCodes?.length) {
49
+ if (!constraints.allowedCodes.includes(metadata.code)) {
50
+ return {
51
+ approved: false,
52
+ reason: "CODE_NOT_ALLOWED",
53
+ detail: `Code "${metadata.code}" not in allowed list`,
54
+ };
55
+ }
56
+ }
57
+ // Code blocklist
58
+ if (metadata?.code && constraints.blockedCodes?.includes(metadata.code)) {
59
+ return {
60
+ approved: false,
61
+ reason: "CODE_BLOCKED",
62
+ detail: `Code "${metadata.code}" is blocked`,
63
+ };
64
+ }
65
+ // Customer allowlist
66
+ if (metadata?.customer && constraints.allowedCustomers?.length) {
67
+ if (!constraints.allowedCustomers.includes(metadata.customer)) {
68
+ return {
69
+ approved: false,
70
+ reason: "CUSTOMER_NOT_ALLOWED",
71
+ detail: `Customer "${metadata.customer}" not in allowed list`,
72
+ };
73
+ }
74
+ }
75
+ // Customer blocklist
76
+ if (metadata?.customer && constraints.blockedCustomers?.includes(metadata.customer)) {
77
+ return {
78
+ approved: false,
79
+ reason: "CUSTOMER_BLOCKED",
80
+ detail: `Customer "${metadata.customer}" is blocked`,
81
+ };
82
+ }
83
+ return {
84
+ approved: true,
85
+ remaining: { budget: remaining - amount, period: policy.budgetPeriod },
86
+ };
87
+ }
88
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Receipt signing & verification — ES256 JWS (JWT), AP2's RECEIPT format.
3
+ *
4
+ * This is a plain compact JWS over a whole JSON payload (alg ES256, JWK keys) —
5
+ * which is exactly how AP2 secures a *Mandate Receipt* (a Verifier-signed JWT
6
+ * with `iss`/`result`/`reference`; see AP2 `jwt_helper.py`). It is NOT how AP2
7
+ * secures a *mandate*: real AP2 mandates are dSD-JWT delegation chains — use the
8
+ * `ap2` namespace (`ap2.verifyChain`, `ap2.receiptReference`, …) for those.
9
+ *
10
+ * Because the whole payload is signed, no field is mutable without breaking the
11
+ * signature — there is no "signed subset vs enforced superset" gap.
12
+ *
13
+ * const token = await signReceipt(receipt, privateJwk); // compact JWS string
14
+ * const { valid, payload } = await verifyReceipt(token, publicJwk);
15
+ */
16
+ import { type JWK } from "jose";
17
+ /** Sign a receipt as a compact JWS (ES256) over the whole payload. */
18
+ export declare function signReceipt(receipt: unknown, privateKey: JWK): Promise<string>;
19
+ export interface VerifiedReceipt<T = unknown> {
20
+ valid: boolean;
21
+ payload?: T;
22
+ error?: string;
23
+ }
24
+ /**
25
+ * Verify a compact JWS receipt (ES256) and return the parsed payload.
26
+ * Returns { valid:false, error } on a bad signature, wrong key, or malformed token.
27
+ */
28
+ export declare function verifyReceipt<T = unknown>(token: string, publicKey: JWK): Promise<VerifiedReceipt<T>>;
29
+ export type { JWK };
30
+ //# sourceMappingURL=receipt-jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-jwt.d.ts","sourceRoot":"","sources":["../src/receipt-jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAyC,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAIvE,sEAAsE;AACtE,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAKpF;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAQ3G;AAED,YAAY,EAAE,GAAG,EAAE,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Receipt signing & verification — ES256 JWS (JWT), AP2's RECEIPT format.
3
+ *
4
+ * This is a plain compact JWS over a whole JSON payload (alg ES256, JWK keys) —
5
+ * which is exactly how AP2 secures a *Mandate Receipt* (a Verifier-signed JWT
6
+ * with `iss`/`result`/`reference`; see AP2 `jwt_helper.py`). It is NOT how AP2
7
+ * secures a *mandate*: real AP2 mandates are dSD-JWT delegation chains — use the
8
+ * `ap2` namespace (`ap2.verifyChain`, `ap2.receiptReference`, …) for those.
9
+ *
10
+ * Because the whole payload is signed, no field is mutable without breaking the
11
+ * signature — there is no "signed subset vs enforced superset" gap.
12
+ *
13
+ * const token = await signReceipt(receipt, privateJwk); // compact JWS string
14
+ * const { valid, payload } = await verifyReceipt(token, publicJwk);
15
+ */
16
+ import { CompactSign, compactVerify, importJWK } from "jose";
17
+ const ALG = "ES256";
18
+ /** Sign a receipt as a compact JWS (ES256) over the whole payload. */
19
+ export async function signReceipt(receipt, privateKey) {
20
+ const key = await importJWK(privateKey, ALG);
21
+ return new CompactSign(new TextEncoder().encode(JSON.stringify(receipt)))
22
+ .setProtectedHeader({ alg: ALG })
23
+ .sign(key);
24
+ }
25
+ /**
26
+ * Verify a compact JWS receipt (ES256) and return the parsed payload.
27
+ * Returns { valid:false, error } on a bad signature, wrong key, or malformed token.
28
+ */
29
+ export async function verifyReceipt(token, publicKey) {
30
+ try {
31
+ const key = await importJWK(publicKey, ALG);
32
+ const { payload } = await compactVerify(token, key, { algorithms: [ALG] });
33
+ return { valid: true, payload: JSON.parse(new TextDecoder().decode(payload)) };
34
+ }
35
+ catch (e) {
36
+ return { valid: false, error: e?.message || "verification failed" };
37
+ }
38
+ }
39
+ //# sourceMappingURL=receipt-jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-jwt.js","sourceRoot":"","sources":["../src/receipt-jwt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAY,MAAM,MAAM,CAAC;AAEvE,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB,EAAE,UAAe;IACjE,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC7C,OAAO,IAAI,WAAW,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;SACtE,kBAAkB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;SAChC,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAc,KAAa,EAAE,SAAc;IAC5E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAM,EAAE,CAAC;IACtF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAG,CAAW,EAAE,OAAO,IAAI,qBAAqB,EAAE,CAAC;IACjF,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Input validation schemas (zod).
3
+ *
4
+ * The untrusted boundary is the runtime spend request — what an agent wants to
5
+ * spend right now. Mandate *integrity* is guaranteed separately by the ES256 JWS
6
+ * signature (see receipt-jwt.ts), so here we validate the request shapes and,
7
+ * above all, the money field.
8
+ *
9
+ * `Cents` is the shared money validator: a positive, safe-integer cent value,
10
+ * accepted as a number or an all-digit string. It rejects fractional, negative,
11
+ * zero, NaN, Infinity, overflow, and any non-digit string — the same rule the
12
+ * hosted Verifier enforces, so self-hosted and hosted agree to the cent.
13
+ */
14
+ import { z } from "zod";
15
+ export declare const Cents: z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
16
+ /** Parse any input into positive cents, or return null (never throws). */
17
+ export declare function parseCents(input: unknown): number | null;
18
+ /** A constraint-check transaction — the input to `checkConstraints`. */
19
+ export declare const ConstraintTxSchema: z.ZodObject<{
20
+ amount: z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
21
+ merchantId: z.ZodOptional<z.ZodString>;
22
+ items: z.ZodOptional<z.ZodArray<z.ZodObject<{
23
+ id: z.ZodString;
24
+ name: z.ZodString;
25
+ quantity: z.ZodNumber;
26
+ unitPrice: z.ZodString;
27
+ currency: z.ZodString;
28
+ category: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strip>>>;
30
+ }, z.core.$strip>;
31
+ /** A policy spend request — the input to `checkPolicy`. */
32
+ export declare const PolicyRequestSchema: z.ZodObject<{
33
+ agentId: z.ZodString;
34
+ amount: z.ZodPipe<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>, z.ZodTransform<number, string | number>>;
35
+ metadata: z.ZodOptional<z.ZodObject<{
36
+ code: z.ZodOptional<z.ZodString>;
37
+ customer: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$loose>>;
39
+ idempotencyKey: z.ZodString;
40
+ }, z.core.$strip>;
41
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,KAAK,qGAKd,CAAC;AAEL,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGxD;AAWD,wEAAwE;AACxE,eAAO,MAAM,kBAAkB;;;;;;;;;;;iBAI7B,CAAC;AAEH,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB;;;;;;;;iBAQ9B,CAAC"}
package/dist/schema.js ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Input validation schemas (zod).
3
+ *
4
+ * The untrusted boundary is the runtime spend request — what an agent wants to
5
+ * spend right now. Mandate *integrity* is guaranteed separately by the ES256 JWS
6
+ * signature (see receipt-jwt.ts), so here we validate the request shapes and,
7
+ * above all, the money field.
8
+ *
9
+ * `Cents` is the shared money validator: a positive, safe-integer cent value,
10
+ * accepted as a number or an all-digit string. It rejects fractional, negative,
11
+ * zero, NaN, Infinity, overflow, and any non-digit string — the same rule the
12
+ * hosted Verifier enforces, so self-hosted and hosted agree to the cent.
13
+ */
14
+ import { z } from "zod";
15
+ export const Cents = z
16
+ .union([z.number(), z.string().regex(/^\d+$/, "must be all digits")])
17
+ .transform((v) => (typeof v === "string" ? Number(v) : v))
18
+ .refine((n) => Number.isSafeInteger(n) && n > 0, {
19
+ message: "amount must be a positive integer (cents)",
20
+ });
21
+ /** Parse any input into positive cents, or return null (never throws). */
22
+ export function parseCents(input) {
23
+ const r = Cents.safeParse(input);
24
+ return r.success ? r.data : null;
25
+ }
26
+ const CartItemSchema = z.object({
27
+ id: z.string(),
28
+ name: z.string(),
29
+ quantity: z.number(),
30
+ unitPrice: z.string(),
31
+ currency: z.string(),
32
+ category: z.string().optional(),
33
+ });
34
+ /** A constraint-check transaction — the input to `checkConstraints`. */
35
+ export const ConstraintTxSchema = z.object({
36
+ amount: Cents,
37
+ merchantId: z.string().optional(),
38
+ items: z.array(CartItemSchema).optional(),
39
+ });
40
+ /** A policy spend request — the input to `checkPolicy`. */
41
+ export const PolicyRequestSchema = z.object({
42
+ agentId: z.string(),
43
+ amount: Cents,
44
+ metadata: z
45
+ .object({ code: z.string().optional(), customer: z.string().optional() })
46
+ .passthrough()
47
+ .optional(),
48
+ idempotencyKey: z.string(),
49
+ });
50
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC;KACnB,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC;KACpE,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACzD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;IAC/C,OAAO,EAAE,2CAA2C;CACrD,CAAC,CAAC;AAEL,0EAA0E;AAC1E,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,KAAK;IACb,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEH,2DAA2D;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,KAAK;IACb,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;SACxE,WAAW,EAAE;SACb,QAAQ,EAAE;IACb,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;CAC3B,CAAC,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * AP2 Mandate Types
3
+ *
4
+ * Core types from the AP2 protocol spec.
5
+ * Used by both the open-source client and the hosted Verifier.
6
+ */
7
+ export interface SpendingConstraint {
8
+ maxAmount: string;
9
+ currency: string;
10
+ categories?: string[];
11
+ allowedMerchants?: string[];
12
+ blockedMerchants?: string[];
13
+ }
14
+ export interface IntentMandate {
15
+ type: "intent-mandate";
16
+ version: "0.1.0";
17
+ id: string;
18
+ user: {
19
+ id: string;
20
+ };
21
+ agent: {
22
+ id: string;
23
+ };
24
+ intent: string;
25
+ constraints: SpendingConstraint;
26
+ validFrom: string;
27
+ validUntil: string;
28
+ maxTransactions?: number;
29
+ budgetTotal: string;
30
+ budgetSpent: string;
31
+ }
32
+ export interface CartMandate {
33
+ type: "cart-mandate";
34
+ version: "0.1.0";
35
+ id: string;
36
+ merchant: {
37
+ id: string;
38
+ name: string;
39
+ url: string;
40
+ };
41
+ agent: {
42
+ id: string;
43
+ };
44
+ user: {
45
+ id: string;
46
+ };
47
+ cart: {
48
+ items: CartItem[];
49
+ total: string;
50
+ currency: string;
51
+ };
52
+ expiresAt: string;
53
+ paymentRails: string[];
54
+ }
55
+ export interface CartItem {
56
+ id: string;
57
+ name: string;
58
+ quantity: number;
59
+ unitPrice: string;
60
+ currency: string;
61
+ category?: string;
62
+ }
63
+ export interface VerifyRequest {
64
+ mandate: IntentMandate | CartMandate;
65
+ transaction: {
66
+ amount: string;
67
+ currency: string;
68
+ items?: CartItem[];
69
+ idempotencyKey: string;
70
+ };
71
+ }
72
+ export interface VerifyResponse {
73
+ approved: boolean;
74
+ verificationId?: string;
75
+ reason?: string;
76
+ detail?: string;
77
+ mandate?: {
78
+ id: string;
79
+ remainingBudget: string;
80
+ remainingTransactions?: number;
81
+ expiresAt: string;
82
+ };
83
+ holdExpiresAt?: string;
84
+ }
85
+ export interface SettleRequest {
86
+ verificationId: string;
87
+ paymentResult: {
88
+ success: boolean;
89
+ transactionId?: string;
90
+ rail?: string;
91
+ };
92
+ }
93
+ export interface MandateSummary {
94
+ id: string;
95
+ budgetSpent: string;
96
+ remainingBudget: string;
97
+ txCount: number;
98
+ }
99
+ export interface SettleResponse {
100
+ settled: boolean;
101
+ released?: boolean;
102
+ mandate?: MandateSummary;
103
+ }
104
+ export interface ReleaseResponse {
105
+ released: boolean;
106
+ mandate?: MandateSummary;
107
+ }
108
+ export interface RefundResponse {
109
+ refundId?: string;
110
+ refundedAmount?: string;
111
+ totalRefunded?: string;
112
+ status?: "refunded" | "partially_refunded";
113
+ idempotentReplay?: boolean;
114
+ mandate?: MandateSummary;
115
+ }
116
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACrB,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACpD,KAAK,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACtB,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACrB,IAAI,EAAE;QACJ,KAAK,EAAE,QAAQ,EAAE,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,aAAa,GAAG,WAAW,CAAC;IACrC,WAAW,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,UAAU,GAAG,oBAAoB,CAAC;IAC3C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * AP2 Mandate Types
3
+ *
4
+ * Core types from the AP2 protocol spec.
5
+ * Used by both the open-source client and the hosted Verifier.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Constraint checking for a verified mandate.
3
+ *
4
+ * Signature verification lives in receipt-jwt.ts (ES256 JWS — AP2's receipt
5
+ * format). Once a mandate's signature is verified there, the WHOLE payload is
6
+ * trusted, and these checks enforce the spending constraints it carries. There
7
+ * is no "signed subset vs enforced superset" gap: every field was under the JWS.
8
+ */
9
+ import type { IntentMandate, CartItem } from "./types.js";
10
+ export interface VerificationResult {
11
+ valid: boolean;
12
+ error?: string;
13
+ }
14
+ /**
15
+ * Check an Intent Mandate's constraints against a proposed transaction.
16
+ * Stateless — does NOT track budget across transactions. For cross-merchant
17
+ * budget tracking, use the hosted Verifier (VerifierClient).
18
+ */
19
+ export declare function checkConstraints(mandate: IntentMandate, transaction: {
20
+ amount: string;
21
+ merchantId?: string;
22
+ items?: CartItem[];
23
+ }): VerificationResult;
24
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAA;CAAE,GACvE,kBAAkB,CAyDpB"}
package/dist/verify.js ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Constraint checking for a verified mandate.
3
+ *
4
+ * Signature verification lives in receipt-jwt.ts (ES256 JWS — AP2's receipt
5
+ * format). Once a mandate's signature is verified there, the WHOLE payload is
6
+ * trusted, and these checks enforce the spending constraints it carries. There
7
+ * is no "signed subset vs enforced superset" gap: every field was under the JWS.
8
+ */
9
+ import { parseCents, ConstraintTxSchema } from "./schema.js";
10
+ /**
11
+ * Check an Intent Mandate's constraints against a proposed transaction.
12
+ * Stateless — does NOT track budget across transactions. For cross-merchant
13
+ * budget tracking, use the hosted Verifier (VerifierClient).
14
+ */
15
+ export function checkConstraints(mandate, transaction) {
16
+ const parsed = ConstraintTxSchema.safeParse(transaction);
17
+ if (!parsed.success) {
18
+ return { valid: false, error: parsed.error.issues[0]?.message ?? "Invalid transaction" };
19
+ }
20
+ const { amount, merchantId, items } = parsed.data;
21
+ const c = mandate.constraints;
22
+ // Temporal — parse explicitly and reject NaN. `new Date("garbage") > now` AND
23
+ // `< now` are both false, which would silently disable the expiry gate.
24
+ const now = Date.now();
25
+ const validFrom = Date.parse(mandate.validFrom);
26
+ const validUntil = Date.parse(mandate.validUntil);
27
+ if (Number.isNaN(validFrom) || Number.isNaN(validUntil)) {
28
+ return { valid: false, error: "Mandate has an invalid or missing validFrom/validUntil" };
29
+ }
30
+ if (validFrom > now)
31
+ return { valid: false, error: `Mandate not yet valid (from ${mandate.validFrom})` };
32
+ if (validUntil < now)
33
+ return { valid: false, error: "Mandate expired" };
34
+ // Per-transaction max
35
+ const maxAmount = parseCents(c.maxAmount);
36
+ if (maxAmount === null) {
37
+ return { valid: false, error: "Mandate maxAmount is not a valid positive integer (cents)" };
38
+ }
39
+ if (amount > maxAmount) {
40
+ return {
41
+ valid: false,
42
+ error: `$${(amount / 100).toFixed(2)} exceeds per-transaction max $${(maxAmount / 100).toFixed(2)}`,
43
+ };
44
+ }
45
+ // Merchant allowlist — if configured, a missing merchantId is a denial, not a skip.
46
+ if (c.allowedMerchants?.length) {
47
+ if (!merchantId || !c.allowedMerchants.includes(merchantId)) {
48
+ return { valid: false, error: `Merchant ${merchantId ?? "(none)"} not in allowlist` };
49
+ }
50
+ }
51
+ // Merchant blocklist
52
+ if (merchantId && c.blockedMerchants?.includes(merchantId)) {
53
+ return { valid: false, error: `Merchant ${merchantId} is blocked` };
54
+ }
55
+ // Category — under a category restriction every item must carry an allowed
56
+ // category; a transaction with no items can't be category-verified, so deny.
57
+ if (c.categories?.length) {
58
+ if (!items?.length) {
59
+ return { valid: false, error: "Category-restricted mandate requires an itemized transaction" };
60
+ }
61
+ for (const item of items) {
62
+ if (!item.category || !c.categories.includes(item.category)) {
63
+ return { valid: false, error: `Category "${item.category ?? "(none)"}" not allowed` };
64
+ }
65
+ }
66
+ }
67
+ return { valid: true };
68
+ }
69
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAO7D;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAsB,EACtB,WAAwE;IAExE,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,qBAAqB,EAAE,CAAC;IAC3F,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAClD,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC;IAE9B,8EAA8E;IAC9E,wEAAwE;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,wDAAwD,EAAE,CAAC;IAC3F,CAAC;IACD,IAAI,SAAS,GAAG,GAAG;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC;IACzG,IAAI,UAAU,GAAG,GAAG;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAExE,sBAAsB;IACtB,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,2DAA2D,EAAE,CAAC;IAC9F,CAAC;IACD,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;SACpG,CAAC;IACJ,CAAC;IAED,oFAAoF;IACpF,IAAI,CAAC,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,UAAU,IAAI,QAAQ,mBAAmB,EAAE,CAAC;QACxF,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,IAAI,UAAU,IAAI,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,UAAU,aAAa,EAAE,CAAC;IACtE,CAAC;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;YACnB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,8DAA8D,EAAE,CAAC;QACjG,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,IAAI,CAAC,QAAQ,IAAI,QAAQ,eAAe,EAAE,CAAC;YACxF,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC"}
package/package.json CHANGED
@@ -1,21 +1,28 @@
1
1
  {
2
2
  "name": "@goodmeta/agent-verifier",
3
- "version": "0.2.0",
3
+ "version": "0.6.0",
4
4
  "description": "Agent spending verification — signature verification, policy-based constraints, and Verifier API client",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
- "build": "tsc",
10
- "demo": "tsx examples/single-merchant.ts"
9
+ "build": "rm -rf dist && tsc",
10
+ "test": "node --import tsx --test test/*.test.ts test/ap2/*.test.ts",
11
+ "demo": "tsx examples/single-merchant.ts",
12
+ "prepublishOnly": "npm run build && npm test"
11
13
  },
12
- "files": ["dist", "README.md"],
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
13
18
  "devDependencies": {
14
- "tsx": "^4.19.0",
15
- "typescript": "^5.7.0"
19
+ "@types/node": "20.19.42",
20
+ "tsx": "4.21.0",
21
+ "typescript": "5.9.3"
16
22
  },
17
23
  "dependencies": {
18
- "viem": "^2.23.0"
24
+ "jose": "6.2.3",
25
+ "zod": "4.4.3"
19
26
  },
20
27
  "license": "MIT"
21
28
  }