@paybond/kit 0.12.4 → 0.12.6

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 (114) hide show
  1. package/dist/agent/facade.d.ts +2 -0
  2. package/dist/agent/facade.js +10 -2
  3. package/dist/agent/guarded-agent.d.ts +3 -1
  4. package/dist/agent/guarded-agent.js +13 -2
  5. package/dist/agent/index.d.ts +2 -2
  6. package/dist/agent/index.js +1 -1
  7. package/dist/agent/instrument.d.ts +3 -0
  8. package/dist/agent/instrument.js +21 -10
  9. package/dist/agent/interceptor.js +19 -0
  10. package/dist/agent/types.d.ts +14 -0
  11. package/dist/agent-receipt-acta.d.ts +58 -0
  12. package/dist/agent-receipt-acta.js +140 -0
  13. package/dist/agent-receipt-inclusion.d.ts +40 -0
  14. package/dist/agent-receipt-inclusion.js +209 -0
  15. package/dist/agent-receipt-owner-disclosure.d.ts +71 -0
  16. package/dist/agent-receipt-owner-disclosure.js +277 -0
  17. package/dist/agent-receipt-pef.d.ts +69 -0
  18. package/dist/agent-receipt-pef.js +121 -0
  19. package/dist/agent-receipt-scitt.d.ts +50 -0
  20. package/dist/agent-receipt-scitt.js +382 -0
  21. package/dist/agent-receipt.d.ts +55 -0
  22. package/dist/agent-receipt.js +297 -4
  23. package/dist/claude-agents/config.d.ts +21 -2
  24. package/dist/claude-agents/config.js +37 -0
  25. package/dist/claude-agents/index.d.ts +1 -1
  26. package/dist/claude-agents/index.js +1 -1
  27. package/dist/cli/agent/demo-loaders.d.ts +1 -0
  28. package/dist/cli/agent/demo-loaders.js +12 -0
  29. package/dist/cli/command-spec.js +16 -1
  30. package/dist/cli/commands/agent.d.ts +4 -0
  31. package/dist/cli/commands/agent.js +107 -1
  32. package/dist/cli/help.js +4 -1
  33. package/dist/cloudflare-agents/config.d.ts +1 -1
  34. package/dist/cloudflare-agents/config.js +2 -2
  35. package/dist/google-adk/config.d.ts +36 -0
  36. package/dist/google-adk/config.js +172 -0
  37. package/dist/google-adk/index.d.ts +2 -0
  38. package/dist/google-adk/index.js +2 -0
  39. package/dist/google-adk/sandbox-demo.d.ts +32 -0
  40. package/dist/google-adk/sandbox-demo.js +104 -0
  41. package/dist/index.d.ts +10 -2
  42. package/dist/index.js +11 -3
  43. package/dist/init.js +29 -0
  44. package/dist/mcp-receipt-resource.js +3 -1
  45. package/dist/mcp-server.js +182 -10
  46. package/dist/policy/adapter-options.d.ts +9 -0
  47. package/dist/policy/adapter-options.js +11 -0
  48. package/dist/policy/index.d.ts +1 -0
  49. package/dist/policy/index.js +1 -0
  50. package/dist/policy/load.d.ts +7 -0
  51. package/dist/policy/load.js +13 -0
  52. package/dist/policy/merge.js +26 -0
  53. package/dist/policy/schema.d.ts +20 -0
  54. package/dist/policy/schema.js +34 -2
  55. package/dist/shopify/instrument.d.ts +8 -8
  56. package/dist/template-init.d.ts +2 -2
  57. package/dist/template-init.js +12 -4
  58. package/dist/vercel-ai/config.d.ts +2 -1
  59. package/dist/vercel-ai/config.js +2 -2
  60. package/dist/vercel-ai/index.d.ts +2 -1
  61. package/dist/vercel-ai/index.js +2 -1
  62. package/dist/vercel-ai/provider-executed.d.ts +7 -0
  63. package/dist/vercel-ai/provider-executed.js +20 -0
  64. package/dist/vercel-ai/tool-approval.d.ts +5 -0
  65. package/dist/vercel-ai/tool-approval.js +8 -1
  66. package/dist/vercel-ai/wrap-tools.d.ts +8 -1
  67. package/dist/vercel-ai/wrap-tools.js +17 -4
  68. package/glama.json +6 -0
  69. package/package.json +15 -5
  70. package/templates/manifest.json +57 -12
  71. package/templates/openai-shopping-agent/package-lock.json +379 -14
  72. package/templates/openai-shopping-agent/package.json +2 -2
  73. package/templates/paybond-aws-operator/package-lock.json +376 -11
  74. package/templates/paybond-aws-operator/package.json +2 -2
  75. package/templates/paybond-claude-agents-demo/package-lock.json +379 -14
  76. package/templates/paybond-claude-agents-demo/package.json +2 -2
  77. package/templates/paybond-cloudflare-shopping-agent/.env.example +3 -0
  78. package/templates/paybond-cloudflare-shopping-agent/.github/workflows/smoke.yml +20 -0
  79. package/templates/paybond-cloudflare-shopping-agent/LICENSE +201 -0
  80. package/templates/paybond-cloudflare-shopping-agent/README.md +29 -0
  81. package/templates/paybond-cloudflare-shopping-agent/package-lock.json +2671 -0
  82. package/templates/paybond-cloudflare-shopping-agent/package.json +23 -0
  83. package/templates/paybond-cloudflare-shopping-agent/paybond.policy.yaml +22 -0
  84. package/templates/paybond-cloudflare-shopping-agent/src/agent.ts +109 -0
  85. package/templates/paybond-cloudflare-shopping-agent/src/index.ts +22 -0
  86. package/templates/paybond-cloudflare-shopping-agent/src/paybond.config.ts +51 -0
  87. package/templates/paybond-cloudflare-shopping-agent/tsconfig.json +13 -0
  88. package/templates/paybond-crewai-procurement-agent/.env.example +3 -0
  89. package/templates/paybond-crewai-procurement-agent/.github/workflows/smoke.yml +19 -0
  90. package/templates/paybond-crewai-procurement-agent/LICENSE +201 -0
  91. package/templates/paybond-crewai-procurement-agent/README.md +73 -0
  92. package/templates/paybond-crewai-procurement-agent/app.py +79 -0
  93. package/templates/paybond-crewai-procurement-agent/crew.py +117 -0
  94. package/templates/paybond-crewai-procurement-agent/package.json +6 -0
  95. package/templates/paybond-crewai-procurement-agent/paybond.policy.yaml +28 -0
  96. package/templates/paybond-crewai-procurement-agent/paybond_config.py +45 -0
  97. package/templates/paybond-crewai-procurement-agent/requirements.txt +2 -0
  98. package/templates/paybond-invoice-agent/requirements.txt +1 -1
  99. package/templates/paybond-mastra-travel-agent/package-lock.json +379 -14
  100. package/templates/paybond-mastra-travel-agent/package.json +2 -2
  101. package/templates/paybond-mcp-coding-agent/package-lock.json +376 -11
  102. package/templates/paybond-mcp-coding-agent/package.json +2 -2
  103. package/templates/paybond-openai-agents-demo/package-lock.json +379 -14
  104. package/templates/paybond-openai-agents-demo/package.json +2 -2
  105. package/templates/paybond-procurement-agent/package-lock.json +376 -11
  106. package/templates/paybond-procurement-agent/package.json +2 -2
  107. package/templates/paybond-shopify-shopping-agent/package-lock.json +376 -11
  108. package/templates/paybond-shopify-shopping-agent/package.json +2 -2
  109. package/templates/paybond-stripe-agent-demo/package-lock.json +376 -11
  110. package/templates/paybond-stripe-agent-demo/package.json +2 -2
  111. package/templates/paybond-travel-agent/package-lock.json +376 -11
  112. package/templates/paybond-travel-agent/package.json +2 -2
  113. package/templates/paybond-vercel-shopping-agent/package-lock.json +376 -11
  114. package/templates/paybond-vercel-shopping-agent/package.json +2 -2
@@ -14,10 +14,19 @@ export const AGENT_RECEIPT_SIGNING_KEYS_WELL_KNOWN_PATH = "/.well-known/agent-re
14
14
  export const PAYBOND_AGENT_RECEIPT_ATTESTATIONS_HEADER = "x-paybond-agent-receipt-attestations";
15
15
  /** Optional agent run id bound to the attestation header for server-side audit. */
16
16
  export const PAYBOND_AGENT_RECEIPT_SOURCE_RUN_HEADER = "x-paybond-agent-run-id";
17
+ /** AP2 signed-mandate digest kind promoted into authorization.mandate_digest_sha256_hex. */
18
+ export const EXTERNAL_ATTESTATION_KIND_AGENT_MANDATE_V1 = "agent_mandate_v1";
19
+ export const SETTLEMENT_OUTCOME_SETTLED = "SETTLED";
20
+ export const SETTLEMENT_OUTCOME_PENDING_FINALITY = "PENDING_FINALITY";
21
+ export const SETTLEMENT_OUTCOME_REVERSED = "REVERSED";
22
+ export const SETTLEMENT_OUTCOME_FAILED = "FAILED";
17
23
  const SCOPE_TOKEN_RE = /^[a-z0-9][a-z0-9._:/-]{0,127}$/;
18
24
  const HEX64_RE = /^[0-9a-f]{64}$/;
19
25
  const CURRENCY_RE = /^[a-z]{3}$/;
20
26
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
27
+ export const AGENT_RECEIPT_VALIDITY_TIER_OPERATIONAL = "operational";
28
+ export const AGENT_RECEIPT_VALIDITY_TIER_PRIMARY = "primary";
29
+ export const AGENT_RECEIPT_VALIDITY_TIER_ATTESTED = "attested";
21
30
  function sha256Hex(data) {
22
31
  return createHash("sha256").update(data).digest("hex");
23
32
  }
@@ -125,9 +134,10 @@ function normalizeReceipt(receipt) {
125
134
  throw new Error("agent receipt: tenant_id is required");
126
135
  }
127
136
  const authorization = normalizeAuthorization(receipt.authorization);
128
- const outcome = normalizeOutcome(receipt.outcome);
129
137
  const references = normalizeReferences(receipt.references);
130
138
  const externalAttestations = normalizeExternalAttestations(receipt.external_attestations ?? []);
139
+ verifyMandateAuthorizationConsistency(authorization, externalAttestations);
140
+ const outcome = normalizeOutcome(receipt.outcome, scope);
131
141
  let execution;
132
142
  if (scope === AGENT_RECEIPT_SCOPE_ACTION) {
133
143
  if (!receipt.execution) {
@@ -151,6 +161,7 @@ function normalizeReceipt(receipt) {
151
161
  outcome,
152
162
  references,
153
163
  external_attestations: externalAttestations,
164
+ continuity: receipt.continuity ? normalizeContinuity(receipt.continuity, execution) : undefined,
154
165
  operator_attestation: receipt.operator_attestation
155
166
  ? normalizeOperatorAttestation(receipt.operator_attestation)
156
167
  : undefined,
@@ -162,6 +173,32 @@ function normalizeReceipt(receipt) {
162
173
  verifyReceiptId(normalized);
163
174
  return normalized;
164
175
  }
176
+ function normalizeContinuity(continuity, execution) {
177
+ const runId = continuity.run_id.trim().toLowerCase();
178
+ if (!UUID_RE.test(runId)) {
179
+ throw new Error("agent receipt: continuity.run_id must be a canonical UUID");
180
+ }
181
+ if (!Number.isInteger(continuity.sequence_number) || continuity.sequence_number < 1) {
182
+ throw new Error("agent receipt: continuity.sequence_number must be an integer >= 1");
183
+ }
184
+ const prev = continuity.prev_message_digest_sha256_hex?.trim().toLowerCase() ?? "";
185
+ if (continuity.sequence_number === 1) {
186
+ if (prev) {
187
+ throw new Error("agent receipt: continuity.sequence_number 1 must not set prev_message_digest_sha256_hex");
188
+ }
189
+ }
190
+ else {
191
+ requireHex64(prev, "continuity.prev_message_digest_sha256_hex");
192
+ }
193
+ if (execution && execution.run_id !== runId) {
194
+ throw new Error("agent receipt: continuity.run_id must match execution.run_id");
195
+ }
196
+ return {
197
+ ...(prev ? { prev_message_digest_sha256_hex: prev } : {}),
198
+ sequence_number: continuity.sequence_number,
199
+ run_id: runId,
200
+ };
201
+ }
165
202
  function normalizeOperatorAttestation(attestation) {
166
203
  const operatorDid = attestation.operator_did.trim();
167
204
  if (!operatorDid) {
@@ -190,6 +227,20 @@ function normalizeAuthorization(authorization) {
190
227
  if (authorization.requested_spend_cents < 0) {
191
228
  throw new Error("agent receipt: requested_spend_cents must be non-negative");
192
229
  }
230
+ let mandateDigest;
231
+ if (authorization.mandate_digest_sha256_hex) {
232
+ mandateDigest = authorization.mandate_digest_sha256_hex.trim().toLowerCase();
233
+ requireHex64(mandateDigest, "mandate_digest_sha256_hex");
234
+ }
235
+ const mandateReferenceId = authorization.mandate_reference_id?.trim() || undefined;
236
+ if (mandateReferenceId && !mandateDigest) {
237
+ throw new Error("agent receipt: mandate_reference_id requires mandate_digest_sha256_hex");
238
+ }
239
+ let zkPolicyProofDigest;
240
+ if (authorization.zk_policy_proof_digest_sha256_hex) {
241
+ zkPolicyProofDigest = authorization.zk_policy_proof_digest_sha256_hex.trim().toLowerCase();
242
+ requireHex64(zkPolicyProofDigest, "zk_policy_proof_digest_sha256_hex");
243
+ }
193
244
  return {
194
245
  principal_did: principalDid,
195
246
  actor_subject: actorSubject,
@@ -201,6 +252,9 @@ function normalizeAuthorization(authorization) {
201
252
  requested_spend_cents: authorization.requested_spend_cents,
202
253
  currency,
203
254
  reason_codes: normalizeScopeSet(authorization.reason_codes, "reason_codes"),
255
+ ...(mandateDigest ? { mandate_digest_sha256_hex: mandateDigest } : {}),
256
+ ...(mandateReferenceId ? { mandate_reference_id: mandateReferenceId } : {}),
257
+ ...(zkPolicyProofDigest ? { zk_policy_proof_digest_sha256_hex: zkPolicyProofDigest } : {}),
204
258
  };
205
259
  }
206
260
  function normalizeAgent(agent) {
@@ -255,6 +309,11 @@ function normalizeExecution(execution) {
255
309
  if ((execution.duration_ms ?? 0) < 0) {
256
310
  throw new Error("agent receipt: duration_ms must be non-negative");
257
311
  }
312
+ let teeAttestationDigest;
313
+ if (execution.tee_attestation_digest_sha256_hex) {
314
+ teeAttestationDigest = execution.tee_attestation_digest_sha256_hex.trim().toLowerCase();
315
+ requireHex64(teeAttestationDigest, "tee_attestation_digest_sha256_hex");
316
+ }
258
317
  return {
259
318
  run_id: parseUuid(execution.run_id, "run_id"),
260
319
  tool_call_id: toolCallId,
@@ -266,6 +325,7 @@ function normalizeExecution(execution) {
266
325
  started_at: formatRfc3339Seconds(execution.started_at),
267
326
  completed_at: formatRfc3339Seconds(execution.completed_at),
268
327
  duration_ms: execution.duration_ms,
328
+ ...(teeAttestationDigest ? { tee_attestation_digest_sha256_hex: teeAttestationDigest } : {}),
269
329
  };
270
330
  }
271
331
  function normalizeMerchant(merchant) {
@@ -321,7 +381,7 @@ function normalizePayment(payment) {
321
381
  funding_receipt_digest_sha256_hex: fundingDigest,
322
382
  };
323
383
  }
324
- function normalizeOutcome(outcome) {
384
+ function normalizeOutcome(outcome, scope) {
325
385
  const harborState = normalizeScopeToken(outcome.harbor_state, "harbor_state");
326
386
  let spendReservationOutcome;
327
387
  if (outcome.spend_reservation_outcome) {
@@ -331,12 +391,49 @@ function normalizeOutcome(outcome) {
331
391
  }
332
392
  spendReservationOutcome = normalized;
333
393
  }
394
+ let settlementOutcome;
395
+ if (outcome.settlement_outcome) {
396
+ const normalized = outcome.settlement_outcome.trim();
397
+ if (![
398
+ SETTLEMENT_OUTCOME_SETTLED,
399
+ SETTLEMENT_OUTCOME_PENDING_FINALITY,
400
+ SETTLEMENT_OUTCOME_REVERSED,
401
+ SETTLEMENT_OUTCOME_FAILED,
402
+ ].includes(normalized)) {
403
+ throw new Error("agent receipt: settlement_outcome must be SETTLED, PENDING_FINALITY, REVERSED, or FAILED");
404
+ }
405
+ if (scope !== AGENT_RECEIPT_SCOPE_INTENT_TERMINAL) {
406
+ throw new Error("agent receipt: settlement_outcome is only valid for intent_terminal scope");
407
+ }
408
+ settlementOutcome = normalized;
409
+ }
334
410
  return {
335
411
  harbor_state: harborState,
336
412
  spend_reservation_outcome: spendReservationOutcome,
337
413
  predicate_passed: outcome.predicate_passed,
414
+ ...(settlementOutcome ? { settlement_outcome: settlementOutcome } : {}),
338
415
  };
339
416
  }
417
+ function verifyMandateAuthorizationConsistency(authorization, attestations) {
418
+ const digest = authorization.mandate_digest_sha256_hex?.trim().toLowerCase() ?? "";
419
+ const refId = authorization.mandate_reference_id?.trim() ?? "";
420
+ if (!digest && !refId) {
421
+ return;
422
+ }
423
+ if (!digest) {
424
+ throw new Error("agent receipt: mandate_reference_id requires mandate_digest_sha256_hex");
425
+ }
426
+ requireHex64(digest, "mandate_digest_sha256_hex");
427
+ const matched = attestations.find((entry) => entry.kind.trim() === EXTERNAL_ATTESTATION_KIND_AGENT_MANDATE_V1 &&
428
+ entry.digest_sha256_hex.trim().toLowerCase() === digest);
429
+ if (!matched) {
430
+ throw new Error(`agent receipt: mandate_digest_sha256_hex must match an external_attestations entry of kind ${EXTERNAL_ATTESTATION_KIND_AGENT_MANDATE_V1}`);
431
+ }
432
+ const attestationRef = matched.reference_id?.trim() ?? "";
433
+ if (refId && refId !== attestationRef) {
434
+ throw new Error("agent receipt: mandate_reference_id must match the matching external_attestations reference_id");
435
+ }
436
+ }
340
437
  function normalizeReferences(references) {
341
438
  if ((references.ledger_seq ?? 0) < 0) {
342
439
  throw new Error("agent receipt: ledger_seq must be non-negative");
@@ -426,6 +523,17 @@ function marshalCanonicalAgentReceipt(receipt) {
426
523
  ...(receipt.authorization.reason_codes?.length
427
524
  ? { reason_codes: receipt.authorization.reason_codes }
428
525
  : {}),
526
+ ...(receipt.authorization.mandate_digest_sha256_hex
527
+ ? { mandate_digest_sha256_hex: receipt.authorization.mandate_digest_sha256_hex }
528
+ : {}),
529
+ ...(receipt.authorization.mandate_reference_id
530
+ ? { mandate_reference_id: receipt.authorization.mandate_reference_id }
531
+ : {}),
532
+ ...(receipt.authorization.zk_policy_proof_digest_sha256_hex
533
+ ? {
534
+ zk_policy_proof_digest_sha256_hex: receipt.authorization.zk_policy_proof_digest_sha256_hex,
535
+ }
536
+ : {}),
429
537
  };
430
538
  const payload = {
431
539
  schema_version: receipt.schema_version,
@@ -451,6 +559,11 @@ function marshalCanonicalAgentReceipt(receipt) {
451
559
  started_at: receipt.execution.started_at,
452
560
  completed_at: receipt.execution.completed_at,
453
561
  ...(receipt.execution.duration_ms ? { duration_ms: receipt.execution.duration_ms } : {}),
562
+ ...(receipt.execution.tee_attestation_digest_sha256_hex
563
+ ? {
564
+ tee_attestation_digest_sha256_hex: receipt.execution.tee_attestation_digest_sha256_hex,
565
+ }
566
+ : {}),
454
567
  };
455
568
  }
456
569
  if (receipt.merchant) {
@@ -495,6 +608,9 @@ function marshalCanonicalAgentReceipt(receipt) {
495
608
  ...(receipt.outcome.predicate_passed !== undefined
496
609
  ? { predicate_passed: receipt.outcome.predicate_passed }
497
610
  : {}),
611
+ ...(receipt.outcome.settlement_outcome
612
+ ? { settlement_outcome: receipt.outcome.settlement_outcome }
613
+ : {}),
498
614
  };
499
615
  payload.references = {
500
616
  intent_id: receipt.references.intent_id,
@@ -503,6 +619,15 @@ function marshalCanonicalAgentReceipt(receipt) {
503
619
  };
504
620
  payload.external_attestations =
505
621
  receipt.external_attestations.length > 0 ? receipt.external_attestations : null;
622
+ if (receipt.continuity) {
623
+ payload.continuity = {
624
+ ...(receipt.continuity.prev_message_digest_sha256_hex
625
+ ? { prev_message_digest_sha256_hex: receipt.continuity.prev_message_digest_sha256_hex }
626
+ : {}),
627
+ sequence_number: receipt.continuity.sequence_number,
628
+ run_id: receipt.continuity.run_id,
629
+ };
630
+ }
506
631
  return new TextEncoder().encode(JSON.stringify(payload));
507
632
  }
508
633
  /** Returns canonical signing bytes for a normalized receipt body. */
@@ -531,10 +656,165 @@ function allowsOperatorPublicKeyHex(operatorPublicKeyHex, trustedOperatorPublicK
531
656
  const normalized = operatorPublicKeyHex.trim().toLowerCase();
532
657
  return trustedOperatorPublicKeys.some((value) => value.trim().toLowerCase() === normalized);
533
658
  }
659
+ function normalizeValidityTier(value) {
660
+ const normalized = (value ?? "").trim().toLowerCase();
661
+ switch (normalized) {
662
+ case "":
663
+ case AGENT_RECEIPT_VALIDITY_TIER_OPERATIONAL:
664
+ return AGENT_RECEIPT_VALIDITY_TIER_OPERATIONAL;
665
+ case AGENT_RECEIPT_VALIDITY_TIER_PRIMARY:
666
+ return AGENT_RECEIPT_VALIDITY_TIER_PRIMARY;
667
+ case AGENT_RECEIPT_VALIDITY_TIER_ATTESTED:
668
+ return AGENT_RECEIPT_VALIDITY_TIER_ATTESTED;
669
+ default:
670
+ throw new Error(`agent receipt: unknown validity_tier ${JSON.stringify(value)}`);
671
+ }
672
+ }
673
+ function requirePrimaryValidity(receipt) {
674
+ if (!receipt.evidence) {
675
+ throw new Error("agent receipt: primary validity requires evidence");
676
+ }
677
+ const digest = receipt.evidence.payee_signature_digest_sha256_hex?.trim().toLowerCase() ?? "";
678
+ if (!digest) {
679
+ throw new Error("agent receipt: primary validity requires evidence.payee_signature_digest_sha256_hex");
680
+ }
681
+ requireHex64(digest, "evidence.payee_signature_digest_sha256_hex");
682
+ if (receipt.payment && receipt.payment.intent_id !== receipt.references.intent_id) {
683
+ throw new Error("agent receipt: primary validity: payment.intent_id must match references.intent_id");
684
+ }
685
+ if (receipt.merchant &&
686
+ receipt.merchant.payee_did.trim() !== "" &&
687
+ receipt.evidence.payee_did.trim() !== "" &&
688
+ receipt.merchant.payee_did.trim() !== receipt.evidence.payee_did.trim()) {
689
+ throw new Error("agent receipt: primary validity: evidence.payee_did must match merchant.payee_did");
690
+ }
691
+ }
692
+ function requireAttestedValidity(receipt, trustedOperatorPublicKeys) {
693
+ if (!receipt.operator_attestation) {
694
+ throw new Error("agent receipt: attested validity requires operator_attestation");
695
+ }
696
+ if (!allowsOperatorPublicKeyHex(receipt.operator_attestation.signing_public_key_ed25519_hex, trustedOperatorPublicKeys)) {
697
+ throw new Error("agent receipt: attested validity requires operator_attestation signing key in the configured tenant operator registry");
698
+ }
699
+ }
700
+ /** Returns the highest validity tier met under the given registry options. */
701
+ export function achievedValidityTier(receipt, options = {}) {
702
+ try {
703
+ requirePrimaryValidity(receipt);
704
+ }
705
+ catch {
706
+ return AGENT_RECEIPT_VALIDITY_TIER_OPERATIONAL;
707
+ }
708
+ if (receipt.operator_attestation &&
709
+ allowsOperatorPublicKeyHex(receipt.operator_attestation.signing_public_key_ed25519_hex, options.trustedOperatorPublicKeys)) {
710
+ return AGENT_RECEIPT_VALIDITY_TIER_ATTESTED;
711
+ }
712
+ return AGENT_RECEIPT_VALIDITY_TIER_PRIMARY;
713
+ }
714
+ /**
715
+ * Builds the next continuity link from a prior signed action receipt for the same run.
716
+ * When `prior` is omitted, returns sequence 1 with no prev digest.
717
+ */
718
+ export function continuityFromPrior(runId, prior) {
719
+ const normalizedRunId = runId.trim().toLowerCase();
720
+ if (!UUID_RE.test(normalizedRunId)) {
721
+ throw new Error("agent receipt: continuity.run_id must be a canonical UUID");
722
+ }
723
+ if (!prior) {
724
+ return {
725
+ sequence_number: 1,
726
+ run_id: normalizedRunId,
727
+ };
728
+ }
729
+ let priorRunId = normalizedRunId;
730
+ if (prior.continuity?.run_id?.trim()) {
731
+ priorRunId = prior.continuity.run_id.trim().toLowerCase();
732
+ }
733
+ else if (prior.execution?.run_id?.trim()) {
734
+ priorRunId = prior.execution.run_id.trim().toLowerCase();
735
+ }
736
+ if (priorRunId !== normalizedRunId) {
737
+ throw new Error("agent receipt: continuity prior run_id mismatch");
738
+ }
739
+ const prevDigest = prior.message_digest_sha256_hex.trim().toLowerCase();
740
+ requireHex64(prevDigest, "prior message_digest_sha256_hex");
741
+ const seq = prior.continuity && prior.continuity.sequence_number > 0
742
+ ? prior.continuity.sequence_number + 1
743
+ : 2;
744
+ return {
745
+ prev_message_digest_sha256_hex: prevDigest,
746
+ sequence_number: seq,
747
+ run_id: normalizedRunId,
748
+ };
749
+ }
750
+ /**
751
+ * Validates an ordered set of action receipts that declare continuity.
752
+ * Receipts without continuity are ignored. Broken links fail closed.
753
+ */
754
+ export function verifyContinuityChain(receipts) {
755
+ const linked = receipts
756
+ .filter((receipt) => receipt.continuity != null)
757
+ .map((receipt) => normalizeReceipt(receipt))
758
+ .sort((a, b) => {
759
+ const aRun = a.continuity?.run_id ?? "";
760
+ const bRun = b.continuity?.run_id ?? "";
761
+ if (aRun === bRun) {
762
+ return (a.continuity?.sequence_number ?? 0) - (b.continuity?.sequence_number ?? 0);
763
+ }
764
+ return aRun < bRun ? -1 : 1;
765
+ });
766
+ if (linked.length === 0) {
767
+ return;
768
+ }
769
+ const prevByRun = new Map();
770
+ for (const item of linked) {
771
+ const continuity = item.continuity;
772
+ if (!continuity) {
773
+ continue;
774
+ }
775
+ const prior = prevByRun.get(continuity.run_id);
776
+ if (!prior) {
777
+ if (continuity.sequence_number !== 1 || continuity.prev_message_digest_sha256_hex) {
778
+ throw new Error(`agent receipt: continuity chain for run ${continuity.run_id} must start at sequence_number 1 without prev digest`);
779
+ }
780
+ prevByRun.set(continuity.run_id, item);
781
+ continue;
782
+ }
783
+ const expectedSeq = (prior.continuity?.sequence_number ?? 1) + 1;
784
+ if (continuity.sequence_number !== expectedSeq) {
785
+ throw new Error(`agent receipt: continuity chain sequence gap for run ${continuity.run_id}: got ${continuity.sequence_number} want ${expectedSeq}`);
786
+ }
787
+ if (continuity.prev_message_digest_sha256_hex !== prior.message_digest_sha256_hex) {
788
+ throw new Error(`agent receipt: continuity chain digest mismatch for run ${continuity.run_id} sequence ${continuity.sequence_number}`);
789
+ }
790
+ prevByRun.set(continuity.run_id, item);
791
+ }
792
+ }
793
+ function verifyContinuityExpectedPrior(receipt, expectedPriorMessageDigestHex) {
794
+ const expected = expectedPriorMessageDigestHex?.trim().toLowerCase() ?? "";
795
+ if (!expected) {
796
+ return;
797
+ }
798
+ if (!receipt.continuity) {
799
+ throw new Error("agent receipt: continuity is required when an expected prior digest is configured");
800
+ }
801
+ if (receipt.continuity.sequence_number < 2) {
802
+ throw new Error("agent receipt: continuity: expected prior digest requires sequence_number > 1");
803
+ }
804
+ if (receipt.continuity.prev_message_digest_sha256_hex !== expected) {
805
+ throw new Error("agent receipt: continuity: prev_message_digest_sha256_hex does not match expected prior digest");
806
+ }
807
+ }
534
808
  /** Validates structure, receipt_id derivation, digest, and detached Ed25519 signature. */
535
809
  export async function verifyAgentReceiptV1(receipt, options = {}) {
536
810
  ensureEd25519Sha512Sync();
811
+ const requiredTier = normalizeValidityTier(options.requiredValidityTier);
812
+ const verifyOperatorAgainstRegistry = options.verifyOperatorAgainstRegistry === true ||
813
+ requiredTier === AGENT_RECEIPT_VALIDITY_TIER_ATTESTED
814
+ ? true
815
+ : options.verifyOperatorAgainstRegistry;
537
816
  const normalized = normalizeReceipt(receipt);
817
+ verifyContinuityExpectedPrior(normalized, options.expectedPriorMessageDigestHex);
538
818
  if (!allowsSigningPublicKeyHex(normalized.signing_public_key_ed25519_hex, options.expectedSigningPublicKeys)) {
539
819
  throw new Error("agent receipt: signing_public_key_ed25519_hex is not in the configured trusted key set");
540
820
  }
@@ -557,7 +837,17 @@ export async function verifyAgentReceiptV1(receipt, options = {}) {
557
837
  if (!valid) {
558
838
  throw new Error("agent receipt: ed25519 signature verification failed");
559
839
  }
560
- await verifyOperatorAttestation(normalized, digest, options);
840
+ await verifyOperatorAttestation(normalized, digest, {
841
+ ...options,
842
+ verifyOperatorAgainstRegistry,
843
+ });
844
+ if (requiredTier === AGENT_RECEIPT_VALIDITY_TIER_PRIMARY) {
845
+ requirePrimaryValidity(normalized);
846
+ }
847
+ else if (requiredTier === AGENT_RECEIPT_VALIDITY_TIER_ATTESTED) {
848
+ requirePrimaryValidity(normalized);
849
+ requireAttestedValidity(normalized, options.trustedOperatorPublicKeys);
850
+ }
561
851
  return normalized;
562
852
  }
563
853
  /** Validate raw JSON (schema + forbidden fields) then verify signature. */
@@ -583,7 +873,10 @@ async function verifyOperatorAttestation(receipt, gatewayDigest, options = {}) {
583
873
  if (attestation.message_digest_sha256_hex !== receipt.message_digest_sha256_hex) {
584
874
  throw new Error("agent receipt: operator_attestation message_digest_sha256_hex must match gateway digest");
585
875
  }
586
- if (options.verifyOperatorAgainstRegistry &&
876
+ const enforceRegistry = options.verifyOperatorAgainstRegistry === true ||
877
+ (options.verifyOperatorAgainstRegistry !== false &&
878
+ options.trustMode === "tenant_registry");
879
+ if (enforceRegistry &&
587
880
  !allowsOperatorPublicKeyHex(attestation.signing_public_key_ed25519_hex, options.trustedOperatorPublicKeys)) {
588
881
  throw new Error("agent receipt: operator_attestation signing key is not in the configured tenant operator registry");
589
882
  }
@@ -1,13 +1,32 @@
1
1
  import type { SdkMcpToolDefinition } from "@anthropic-ai/claude-agent-sdk";
2
2
  import type { PaybondAgentRun } from "../agent/run.js";
3
- /** Pre-built SDK tool from `tool()` in `@anthropic-ai/claude-agent-sdk`. */
4
- export type ClaudeAgentSdkTool = SdkMcpToolDefinition;
3
+ /**
4
+ * Pre-built SDK tool from `tool()` in `@anthropic-ai/claude-agent-sdk`.
5
+ *
6
+ * Uses `any` for the schema param to match `createSdkMcpServer({ tools })`, which
7
+ * accepts heterogeneous `SdkMcpToolDefinition<any>[]` (per-tool schemas differ).
8
+ */
9
+ export type ClaudeAgentSdkTool = SdkMcpToolDefinition<any>;
10
+ /** Built-in Claude Agent SDK tools that execute outside Paybond MCP and stay unguarded. */
11
+ export declare const CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES: readonly ["Read", "Write", "Edit", "Bash", "Glob", "Grep", "WebFetch", "WebSearch", "NotebookEdit", "Task"];
12
+ export type ClaudeAgentSdkBuiltinToolName = (typeof CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES)[number];
5
13
  export type PaybondClaudeAgentsConfigOptions = {
6
14
  /** MCP server name; defaults to `"paybond"`. */
7
15
  serverName?: string;
8
16
  /** Optional version passed to `createSdkMcpServer`. */
9
17
  serverVersion?: string;
18
+ /**
19
+ * When true (default), emit a console warning if `queryAllowedTools` includes built-in SDK tools
20
+ * that bypass Paybond Harbor verify and auto-evidence.
21
+ */
22
+ warnOnUnguardedBuiltins?: boolean;
23
+ /** `allowedTools` passed to Claude Agent SDK `query()` — used for built-in coverage warnings. */
24
+ queryAllowedTools?: readonly string[];
10
25
  };
26
+ /** Returns built-in SDK tool names present in a query `allowedTools` list. */
27
+ export declare function findUnguardedClaudeBuiltinTools(queryAllowedTools: readonly string[] | undefined): ClaudeAgentSdkBuiltinToolName[];
28
+ /** Warn once per process when built-in Claude SDK tools remain enabled alongside Paybond MCP tools. */
29
+ export declare function warnOnUnguardedClaudeBuiltinTools(queryAllowedTools: readonly string[] | undefined): void;
11
30
  export type ClaudeAgentsConfig = {
12
31
  mcpServer: ReturnType<typeof import("@anthropic-ai/claude-agent-sdk").createSdkMcpServer>;
13
32
  allowedTools: string[];
@@ -21,6 +21,40 @@ function loadClaudeAgentSdk() {
21
21
  }
22
22
  return cachedClaudeAgentSdk;
23
23
  }
24
+ /** Built-in Claude Agent SDK tools that execute outside Paybond MCP and stay unguarded. */
25
+ export const CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES = [
26
+ "Read",
27
+ "Write",
28
+ "Edit",
29
+ "Bash",
30
+ "Glob",
31
+ "Grep",
32
+ "WebFetch",
33
+ "WebSearch",
34
+ "NotebookEdit",
35
+ "Task",
36
+ ];
37
+ let claudeBuiltinToolsWarningEmitted = false;
38
+ /** Returns built-in SDK tool names present in a query `allowedTools` list. */
39
+ export function findUnguardedClaudeBuiltinTools(queryAllowedTools) {
40
+ if (!queryAllowedTools?.length) {
41
+ return [];
42
+ }
43
+ const allowed = new Set(queryAllowedTools);
44
+ return CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES.filter((name) => allowed.has(name));
45
+ }
46
+ /** Warn once per process when built-in Claude SDK tools remain enabled alongside Paybond MCP tools. */
47
+ export function warnOnUnguardedClaudeBuiltinTools(queryAllowedTools) {
48
+ const unguarded = findUnguardedClaudeBuiltinTools(queryAllowedTools);
49
+ if (unguarded.length === 0 || claudeBuiltinToolsWarningEmitted) {
50
+ return;
51
+ }
52
+ claudeBuiltinToolsWarningEmitted = true;
53
+ console.warn(`[paybond/claude-agents] Unguarded Claude Agent SDK built-in tools remain enabled (${unguarded.join(", ")}). ` +
54
+ "Paybond governs only custom tools registered via tool() in the Paybond MCP server. " +
55
+ "Remove built-ins from allowedTools or restrict the agent to mcp__paybond__* tools. " +
56
+ "See https://docs.paybond.ai/kit/claude-agents#built-in-sdk-tools");
57
+ }
24
58
  function claudeMcpAllowedToolName(serverName, toolName) {
25
59
  return `mcp__${serverName}__${toolName}`;
26
60
  }
@@ -150,6 +184,9 @@ export function createPaybondClaudeAgentsConfig(run, tools, options) {
150
184
  const { createSdkMcpServer } = loadClaudeAgentSdk();
151
185
  const sdkTools = assertClaudeAgentSdkTools(tools);
152
186
  const serverName = options?.serverName?.trim() || "paybond";
187
+ if (options?.warnOnUnguardedBuiltins !== false) {
188
+ warnOnUnguardedClaudeBuiltinTools(options?.queryAllowedTools);
189
+ }
153
190
  for (const sdkTool of sdkTools) {
154
191
  wrapClaudeAgentSdkTool(run, sdkTool);
155
192
  }
@@ -1,2 +1,2 @@
1
- export { createPaybondClaudeAgentsConfig, type ClaudeAgentSdkTool, type ClaudeAgentsConfig, type PaybondClaudeAgentsConfigOptions, } from "./config.js";
1
+ export { CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES, createPaybondClaudeAgentsConfig, findUnguardedClaudeBuiltinTools, type ClaudeAgentSdkBuiltinToolName, type ClaudeAgentSdkTool, type ClaudeAgentsConfig, type PaybondClaudeAgentsConfigOptions, warnOnUnguardedClaudeBuiltinTools, } from "./config.js";
2
2
  export { runClaudeAgentsSandboxDemo, type RunClaudeAgentsSandboxDemoInput, type RunClaudeAgentsSandboxDemoResult, } from "./sandbox-demo.js";
@@ -1,2 +1,2 @@
1
- export { createPaybondClaudeAgentsConfig, } from "./config.js";
1
+ export { CLAUDE_AGENT_SDK_BUILTIN_TOOL_NAMES, createPaybondClaudeAgentsConfig, findUnguardedClaudeBuiltinTools, warnOnUnguardedClaudeBuiltinTools, } from "./config.js";
2
2
  export { runClaudeAgentsSandboxDemo, } from "./sandbox-demo.js";
@@ -2,5 +2,6 @@ export declare function loadRunVercelAiSandboxDemo(): Promise<typeof import("../
2
2
  export declare function loadRunLangGraphSandboxDemo(): Promise<typeof import("../../langgraph/sandbox-demo.js").runLangGraphSandboxDemo>;
3
3
  export declare function loadRunClaudeAgentsSandboxDemo(): Promise<typeof import("../../claude-agents/sandbox-demo.js").runClaudeAgentsSandboxDemo>;
4
4
  export declare function loadRunOpenAIAgentsSandboxDemo(): Promise<typeof import("../../openai-agents/sandbox-demo.js").runOpenAIAgentsSandboxDemo>;
5
+ export declare function loadRunGoogleAdkSandboxDemo(): Promise<typeof import("../../google-adk/sandbox-demo.js").runGoogleAdkSandboxDemo>;
5
6
  export declare function loadRunMastraSandboxDemo(): Promise<typeof import("../../mastra/sandbox-demo.js").runMastraSandboxDemo>;
6
7
  export declare function loadRunCloudflareAgentsSandboxDemo(): Promise<typeof import("../../cloudflare-agents/sandbox-demo.js").runCloudflareAgentsSandboxDemo>;
@@ -64,6 +64,18 @@ export async function loadRunOpenAIAgentsSandboxDemo() {
64
64
  throw err;
65
65
  }
66
66
  }
67
+ export async function loadRunGoogleAdkSandboxDemo() {
68
+ try {
69
+ const mod = await import("../../google-adk/sandbox-demo.js");
70
+ return mod.runGoogleAdkSandboxDemo;
71
+ }
72
+ catch (err) {
73
+ if (isMissingModuleError(err, "@google/adk")) {
74
+ throw missingPeerDependencyError("@google/adk", "google-adk");
75
+ }
76
+ throw err;
77
+ }
78
+ }
67
79
  export async function loadRunMastraSandboxDemo() {
68
80
  try {
69
81
  const mod = await import("../../mastra/sandbox-demo.js");
@@ -86,6 +86,9 @@ export const COMMAND_PATHS = [
86
86
  "agent demo generic smoke",
87
87
  "agent demo claude-agents smoke",
88
88
  "agent demo crewai smoke",
89
+ "agent demo pydantic-ai smoke",
90
+ "agent demo google-adk smoke",
91
+ "agent demo microsoft-agent-framework smoke",
89
92
  "agent demo openai-agents smoke",
90
93
  "agent demo mastra smoke",
91
94
  "agent demo cloudflare-agents smoke",
@@ -378,7 +381,10 @@ export const COMMAND_EXAMPLES = {
378
381
  "paybond init agent-middleware --framework mastra --out paybond-mastra.ts",
379
382
  "paybond init agent-middleware --framework cloudflare-agents --out paybond-cloudflare-agents.ts",
380
383
  "paybond init agent-middleware --framework mcp --out paybond-mcp.ts",
381
- "paybond init agent-middleware --framework crewai --out paybond_crewai.py"
384
+ "paybond init agent-middleware --framework crewai --out paybond_crewai.py",
385
+ "paybond init agent-middleware --framework pydantic-ai --out paybond_pydantic_ai.py",
386
+ "paybond init agent-middleware --framework google-adk --out paybond_google_adk.py",
387
+ "paybond init agent-middleware --framework microsoft-agent-framework --out paybond_microsoft_agent_framework.py"
382
388
  ],
383
389
  "agent run bind": [
384
390
  "paybond agent run bind --policy-file paybond.policy.yaml --format json",
@@ -430,6 +436,15 @@ export const COMMAND_EXAMPLES = {
430
436
  "agent demo crewai smoke": [
431
437
  "paybond agent demo crewai smoke --operation procurement.submit_po --requested-spend-cents 12000 --evidence-preset cost_and_completion --format json"
432
438
  ],
439
+ "agent demo pydantic-ai smoke": [
440
+ "paybond agent demo pydantic-ai smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json"
441
+ ],
442
+ "agent demo google-adk smoke": [
443
+ "paybond agent demo google-adk smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json"
444
+ ],
445
+ "agent demo microsoft-agent-framework smoke": [
446
+ "paybond agent demo microsoft-agent-framework smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json"
447
+ ],
433
448
  "agent demo openai-agents smoke": [
434
449
  "paybond agent demo openai-agents smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json"
435
450
  ],
@@ -17,5 +17,9 @@ export declare function handleAgentDemoMastraSmoke(ctx: CliContext, argv: string
17
17
  export declare function handleAgentDemoCloudflareAgentsSmoke(ctx: CliContext, argv: string[]): Promise<CommandResult>;
18
18
  export declare function handleAgentDemoClaudeAgentsSmoke(ctx: CliContext, argv: string[]): Promise<CommandResult>;
19
19
  export declare function handleAgentDemoMcpSmoke(ctx: CliContext, argv: string[]): Promise<CommandResult>;
20
+ export declare function handleAgentDemoCrewaiSmoke(_ctx: CliContext, argv: string[]): Promise<CommandResult>;
21
+ export declare function handleAgentDemoPydanticAiSmoke(_ctx: CliContext, argv: string[]): Promise<CommandResult>;
22
+ export declare function handleAgentDemoMicrosoftAgentFrameworkSmoke(_ctx: CliContext, argv: string[]): Promise<CommandResult>;
20
23
  export declare function handleAgentDemoOpenAIAgentsSmoke(ctx: CliContext, argv: string[]): Promise<CommandResult>;
24
+ export declare function handleAgentDemoGoogleAdkSmoke(ctx: CliContext, argv: string[]): Promise<CommandResult>;
21
25
  export declare function handleAgent(ctx: CliContext, group: string, subcommand: string, argv: string[]): Promise<CommandResult>;