@paybond/kit 0.7.0 → 0.8.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.
- package/README.md +25 -25
- package/dist/index.d.ts +64 -0
- package/dist/index.js +80 -0
- package/dist/init.d.ts +2 -0
- package/dist/init.js +148 -0
- package/dist/mcp-server.js +51 -0
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `@paybond/kit`
|
|
2
2
|
|
|
3
|
-
Paybond Kit for TypeScript is the npm package for tenant-bound Paybond integrations. It opens hosted Gateway sessions, verifies capability tokens, signs intent and evidence payloads, uses Stripe Connect or x402 / USDC-on-Base settlement rails,
|
|
3
|
+
Paybond Kit for TypeScript is the npm package for tenant-bound Paybond integrations and delegated agent spend controls. It opens hosted Gateway sessions, verifies capability tokens, authorizes tool-call spend, signs intent and evidence payloads, uses Stripe Connect or x402 / USDC-on-Base settlement rails, reads tenant-scoped Signal, fraud, ledger, protocol, and A2A data, and includes agent-runtime integrations.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -18,7 +18,6 @@ npm install @paybond/kit
|
|
|
18
18
|
|
|
19
19
|
- Node.js 22+
|
|
20
20
|
- A `paybond_sk_sandbox_...` or `paybond_sk_live_...` service-account API key
|
|
21
|
-
- For capability verification: a funded intent id and a capability token minted for that intent
|
|
22
21
|
- For intent creation or evidence submission: 32-byte Ed25519 signing seeds owned by your application
|
|
23
22
|
|
|
24
23
|
Minimal environment for the quick start:
|
|
@@ -27,13 +26,6 @@ Minimal environment for the quick start:
|
|
|
27
26
|
export PAYBOND_API_KEY="paybond_sk_sandbox_..."
|
|
28
27
|
```
|
|
29
28
|
|
|
30
|
-
Optional, if you want the quick start to verify a capability:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
export PAYBOND_INTENT_ID="00000000-0000-0000-0000-000000000000"
|
|
34
|
-
export PAYBOND_CAPABILITY="base64-biscuit-token"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
29
|
## Tenant isolation
|
|
38
30
|
|
|
39
31
|
Every session is bound to the tenant realm echoed by gateway-authenticated service-account introspection.
|
|
@@ -62,27 +54,32 @@ const paybond = await Paybond.open({
|
|
|
62
54
|
|
|
63
55
|
try {
|
|
64
56
|
console.log("tenant realm:", paybond.harbor.tenantId);
|
|
65
|
-
|
|
66
|
-
const intentId = process.env.PAYBOND_INTENT_ID;
|
|
67
|
-
const capability = process.env.PAYBOND_CAPABILITY;
|
|
68
|
-
if (intentId && capability) {
|
|
69
|
-
const verified = await paybond.harbor.verifyCapability({
|
|
70
|
-
intentId,
|
|
71
|
-
token: capability,
|
|
72
|
-
operation: "payments.capture",
|
|
73
|
-
requestedSpendCents: 18_700,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
if (!verified.allow) {
|
|
77
|
-
throw new Error(`verify denied: ${verified.code ?? "deny"} ${verified.message ?? ""}`);
|
|
78
|
-
}
|
|
79
|
-
console.log("capability verified:", verified.auditId);
|
|
80
|
-
}
|
|
81
57
|
} finally {
|
|
82
58
|
await paybond.aclose();
|
|
83
59
|
}
|
|
84
60
|
```
|
|
85
61
|
|
|
62
|
+
## Agent spend controls
|
|
63
|
+
|
|
64
|
+
Use Paybond Kit when an agent workflow needs delegated spend guardrails, tool-call budget checks, paid API or vendor action approval, evidence, release/refund logic, disputes, or audit-ready receipts.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { PaybondCapabilityBinding, PaybondSpendGuard } from "@paybond/kit";
|
|
68
|
+
|
|
69
|
+
const binding = new PaybondCapabilityBinding(paybond.harbor, intentId, capabilityToken);
|
|
70
|
+
const guard = new PaybondSpendGuard(binding);
|
|
71
|
+
const guardedTool = guard.guardTool(
|
|
72
|
+
{ operation: "travel.book_hotel", requestedSpendCents: 20_000 },
|
|
73
|
+
async (input) => bookHotel(input),
|
|
74
|
+
);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Scaffold a wrapper:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npx -p @paybond/kit paybond-init --framework provider-agnostic --out paybond-spend-guard.ts
|
|
81
|
+
```
|
|
82
|
+
|
|
86
83
|
## What the package includes
|
|
87
84
|
|
|
88
85
|
Core SDK:
|
|
@@ -91,6 +88,8 @@ Core SDK:
|
|
|
91
88
|
- `HarborClient` for capability verification, intent creation, x402 funding, evidence submission, and ledger reads
|
|
92
89
|
- `paybond.signal` and `paybond.fraud` on `Paybond` sessions opened from one service-account API key
|
|
93
90
|
- `PaybondIntents` helpers for principal-signed intent creation, x402 funding, and payee-signed evidence submission
|
|
91
|
+
- `PaybondSpendGuard`, `authorizeSpend`, and `guardTool` for spend-named wrappers around capability verification
|
|
92
|
+
- Provider and framework aliases: `paybondOpenAIToolSpendGuard`, `paybondGeminiToolSpendGuard`, `paybondClaudeToolSpendGuard`, `paybondAnthropicToolSpendGuard`, `paybondGoogleAIToolSpendGuard`, `paybondVercelAIToolSpendGuard`, `paybondLangGraphToolSpendGuard`, and `paybondMCPToolSpendGuard`
|
|
94
93
|
|
|
95
94
|
Gateway and trust helpers:
|
|
96
95
|
|
|
@@ -98,6 +97,7 @@ Gateway and trust helpers:
|
|
|
98
97
|
- `GatewayFraudClient` and `ServiceAccountFraudSession` for tenant-scoped fraud assessments, review queues, review events, metrics, and release-gate config
|
|
99
98
|
- Protocol-v2 helpers for mandate verification, replay-safe recognition proof verification, receipt reads, and A2A discovery
|
|
100
99
|
- `paybond-mcp-server` for tenant-bound MCP tool exposure to any MCP-compatible host
|
|
100
|
+
- `paybond-init` for generating a small spend guard wrapper
|
|
101
101
|
|
|
102
102
|
Agent-facing surfaces are model-provider agnostic. Paybond verifies tool operations and tenant scope, not whether a tool call came from OpenAI, Anthropic, Gemini, a local model, or another runtime.
|
|
103
103
|
|
package/dist/index.d.ts
CHANGED
|
@@ -652,7 +652,37 @@ export declare class PaybondCapabilityBinding {
|
|
|
652
652
|
readonly intentId: string;
|
|
653
653
|
readonly capabilityToken: string;
|
|
654
654
|
constructor(harbor: Pick<HarborClient | GatewayHarborClient, "tenantId" | "verifyCapability">, intentId: string, capabilityToken: string);
|
|
655
|
+
verifySpendCapability(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
656
|
+
authorizeSpend(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
655
657
|
}
|
|
658
|
+
export type PaybondSpendAuthorizationInput = {
|
|
659
|
+
operation: string;
|
|
660
|
+
requestedSpendCents?: number;
|
|
661
|
+
};
|
|
662
|
+
export declare class PaybondSpendDeniedError extends Error {
|
|
663
|
+
readonly result: VerifyCapabilityResult;
|
|
664
|
+
constructor(result: VerifyCapabilityResult);
|
|
665
|
+
}
|
|
666
|
+
export type PaybondToolHandler<TArgs extends unknown[], TResult> = (...args: TArgs) => TResult | Promise<TResult>;
|
|
667
|
+
export type PaybondGuardedToolHandler<TArgs extends unknown[], TResult> = (...args: TArgs) => Promise<Awaited<TResult>>;
|
|
668
|
+
export declare class PaybondSpendGuard {
|
|
669
|
+
readonly binding: PaybondCapabilityBinding;
|
|
670
|
+
constructor(binding: PaybondCapabilityBinding);
|
|
671
|
+
verifySpendCapability(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
672
|
+
authorizeSpend(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
673
|
+
assertSpendAuthorized(input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
674
|
+
guardTool<TArgs extends unknown[], TResult>(input: PaybondSpendAuthorizationInput, handler: PaybondToolHandler<TArgs, TResult>): PaybondGuardedToolHandler<TArgs, TResult>;
|
|
675
|
+
}
|
|
676
|
+
export declare function authorizeSpend(binding: PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput): Promise<VerifyCapabilityResult>;
|
|
677
|
+
export declare function guardTool<TArgs extends unknown[], TResult>(binding: PaybondCapabilityBinding, input: PaybondSpendAuthorizationInput, handler: PaybondToolHandler<TArgs, TResult>): PaybondGuardedToolHandler<TArgs, TResult>;
|
|
678
|
+
export declare const paybondOpenAIToolSpendGuard: typeof guardTool;
|
|
679
|
+
export declare const paybondAnthropicToolSpendGuard: typeof guardTool;
|
|
680
|
+
export declare const paybondClaudeToolSpendGuard: typeof guardTool;
|
|
681
|
+
export declare const paybondGeminiToolSpendGuard: typeof guardTool;
|
|
682
|
+
export declare const paybondGoogleAIToolSpendGuard: typeof guardTool;
|
|
683
|
+
export declare const paybondVercelAIToolSpendGuard: typeof guardTool;
|
|
684
|
+
export declare const paybondLangGraphToolSpendGuard: typeof guardTool;
|
|
685
|
+
export declare const paybondMCPToolSpendGuard: typeof guardTool;
|
|
656
686
|
export type PaybondOpenOptions = {
|
|
657
687
|
apiKey: string;
|
|
658
688
|
gatewayBaseUrl?: string;
|
|
@@ -701,6 +731,18 @@ export declare class HarborClient {
|
|
|
701
731
|
operation: string;
|
|
702
732
|
requestedSpendCents?: number;
|
|
703
733
|
}): Promise<VerifyCapabilityResult>;
|
|
734
|
+
verifySpendCapability(input: {
|
|
735
|
+
intentId: string;
|
|
736
|
+
token: string;
|
|
737
|
+
operation: string;
|
|
738
|
+
requestedSpendCents?: number;
|
|
739
|
+
}): Promise<VerifyCapabilityResult>;
|
|
740
|
+
authorizeSpend(input: {
|
|
741
|
+
intentId: string;
|
|
742
|
+
token: string;
|
|
743
|
+
operation: string;
|
|
744
|
+
requestedSpendCents?: number;
|
|
745
|
+
}): Promise<VerifyCapabilityResult>;
|
|
704
746
|
/**
|
|
705
747
|
* POST `/intents` with a principal-signed `CreateIntentRequest` JSON body.
|
|
706
748
|
*
|
|
@@ -787,6 +829,18 @@ export declare class GatewayHarborClient {
|
|
|
787
829
|
operation: string;
|
|
788
830
|
requestedSpendCents?: number;
|
|
789
831
|
}): Promise<VerifyCapabilityResult>;
|
|
832
|
+
verifySpendCapability(input: {
|
|
833
|
+
intentId: string;
|
|
834
|
+
token: string;
|
|
835
|
+
operation: string;
|
|
836
|
+
requestedSpendCents?: number;
|
|
837
|
+
}): Promise<VerifyCapabilityResult>;
|
|
838
|
+
authorizeSpend(input: {
|
|
839
|
+
intentId: string;
|
|
840
|
+
token: string;
|
|
841
|
+
operation: string;
|
|
842
|
+
requestedSpendCents?: number;
|
|
843
|
+
}): Promise<VerifyCapabilityResult>;
|
|
790
844
|
createIntent(body: Record<string, unknown>, options: GatewayHarborMutationOptions): Promise<Record<string, unknown>>;
|
|
791
845
|
fundIntent(intentId: string, options: GatewayHarborMutationOptions & {
|
|
792
846
|
paymentSignature?: string;
|
|
@@ -962,6 +1016,9 @@ export declare class PaybondIntents {
|
|
|
962
1016
|
create(params: PaybondCreateIntentParams & {
|
|
963
1017
|
idempotencyKey?: string;
|
|
964
1018
|
}): Promise<Record<string, unknown>>;
|
|
1019
|
+
createSpendIntent(params: PaybondCreateIntentParams & {
|
|
1020
|
+
idempotencyKey?: string;
|
|
1021
|
+
}): Promise<Record<string, unknown>>;
|
|
965
1022
|
/**
|
|
966
1023
|
* Advance Harbor `/intents/{id}/fund` for x402 / USDC-on-Base intents.
|
|
967
1024
|
*/
|
|
@@ -993,6 +1050,13 @@ export declare class Paybond {
|
|
|
993
1050
|
static open(init: PaybondOpenOptions): Promise<Paybond>;
|
|
994
1051
|
/** Reserved for future HTTP client cleanup; safe to call after work completes. */
|
|
995
1052
|
aclose(): Promise<void>;
|
|
1053
|
+
spendGuard(intentId: string, capabilityToken: string): PaybondSpendGuard;
|
|
1054
|
+
authorizeSpend(input: {
|
|
1055
|
+
intentId: string;
|
|
1056
|
+
token: string;
|
|
1057
|
+
operation: string;
|
|
1058
|
+
requestedSpendCents?: number;
|
|
1059
|
+
}): Promise<VerifyCapabilityResult>;
|
|
996
1060
|
}
|
|
997
1061
|
export { normalizeJson, jsonValueDigest } from "./json-digest.js";
|
|
998
1062
|
export { buildSignedCreateIntentBody, intentCreationSignBytesRaw, type BuildSignedCreateIntentParams, type SettlementRail, } from "./principal-intent.js";
|
package/dist/index.js
CHANGED
|
@@ -156,7 +156,66 @@ export class PaybondCapabilityBinding {
|
|
|
156
156
|
this.intentId = intentId;
|
|
157
157
|
this.capabilityToken = capabilityToken;
|
|
158
158
|
}
|
|
159
|
+
async verifySpendCapability(input) {
|
|
160
|
+
return this.harbor.verifyCapability({
|
|
161
|
+
intentId: this.intentId,
|
|
162
|
+
token: this.capabilityToken,
|
|
163
|
+
operation: input.operation,
|
|
164
|
+
requestedSpendCents: input.requestedSpendCents,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async authorizeSpend(input) {
|
|
168
|
+
return this.verifySpendCapability(input);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export class PaybondSpendDeniedError extends Error {
|
|
172
|
+
result;
|
|
173
|
+
constructor(result) {
|
|
174
|
+
const reason = result.message ?? result.code ?? "denied";
|
|
175
|
+
super(`Paybond spend authorization denied: ${reason}`);
|
|
176
|
+
this.name = "PaybondSpendDeniedError";
|
|
177
|
+
this.result = result;
|
|
178
|
+
}
|
|
159
179
|
}
|
|
180
|
+
export class PaybondSpendGuard {
|
|
181
|
+
binding;
|
|
182
|
+
constructor(binding) {
|
|
183
|
+
this.binding = binding;
|
|
184
|
+
}
|
|
185
|
+
async verifySpendCapability(input) {
|
|
186
|
+
return this.binding.verifySpendCapability(input);
|
|
187
|
+
}
|
|
188
|
+
async authorizeSpend(input) {
|
|
189
|
+
return this.binding.authorizeSpend(input);
|
|
190
|
+
}
|
|
191
|
+
async assertSpendAuthorized(input) {
|
|
192
|
+
const result = await this.authorizeSpend(input);
|
|
193
|
+
if (!result.allow) {
|
|
194
|
+
throw new PaybondSpendDeniedError(result);
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
}
|
|
198
|
+
guardTool(input, handler) {
|
|
199
|
+
return async (...args) => {
|
|
200
|
+
await this.assertSpendAuthorized(input);
|
|
201
|
+
return await handler(...args);
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
export async function authorizeSpend(binding, input) {
|
|
206
|
+
return binding.authorizeSpend(input);
|
|
207
|
+
}
|
|
208
|
+
export function guardTool(binding, input, handler) {
|
|
209
|
+
return new PaybondSpendGuard(binding).guardTool(input, handler);
|
|
210
|
+
}
|
|
211
|
+
export const paybondOpenAIToolSpendGuard = guardTool;
|
|
212
|
+
export const paybondAnthropicToolSpendGuard = guardTool;
|
|
213
|
+
export const paybondClaudeToolSpendGuard = guardTool;
|
|
214
|
+
export const paybondGeminiToolSpendGuard = guardTool;
|
|
215
|
+
export const paybondGoogleAIToolSpendGuard = guardTool;
|
|
216
|
+
export const paybondVercelAIToolSpendGuard = guardTool;
|
|
217
|
+
export const paybondLangGraphToolSpendGuard = guardTool;
|
|
218
|
+
export const paybondMCPToolSpendGuard = guardTool;
|
|
160
219
|
/**
|
|
161
220
|
* HTTP client for Harbor: capability verify, intents, evidence, and tenant-scoped ledger reads
|
|
162
221
|
* (`GET /ledger/v1/*`, PAYBOND-007).
|
|
@@ -329,6 +388,12 @@ export class HarborClient {
|
|
|
329
388
|
message: body.message,
|
|
330
389
|
};
|
|
331
390
|
}
|
|
391
|
+
async verifySpendCapability(input) {
|
|
392
|
+
return this.verifyCapability(input);
|
|
393
|
+
}
|
|
394
|
+
async authorizeSpend(input) {
|
|
395
|
+
return this.verifyCapability(input);
|
|
396
|
+
}
|
|
332
397
|
/**
|
|
333
398
|
* POST `/intents` with a principal-signed `CreateIntentRequest` JSON body.
|
|
334
399
|
*
|
|
@@ -653,6 +718,12 @@ export class GatewayHarborClient {
|
|
|
653
718
|
message: body.message,
|
|
654
719
|
};
|
|
655
720
|
}
|
|
721
|
+
async verifySpendCapability(input) {
|
|
722
|
+
return this.verifyCapability(input);
|
|
723
|
+
}
|
|
724
|
+
async authorizeSpend(input) {
|
|
725
|
+
return this.verifyCapability(input);
|
|
726
|
+
}
|
|
656
727
|
async createIntent(body, options) {
|
|
657
728
|
const { res, text, url } = await this.postJSON("/harbor/intents", body, this.mutationHeaders("createIntent", options));
|
|
658
729
|
if (!res.ok) {
|
|
@@ -1642,6 +1713,9 @@ export class PaybondIntents {
|
|
|
1642
1713
|
});
|
|
1643
1714
|
return this.harbor.createIntent(body, { idempotencyKey, recognitionProof });
|
|
1644
1715
|
}
|
|
1716
|
+
async createSpendIntent(params) {
|
|
1717
|
+
return this.create(params);
|
|
1718
|
+
}
|
|
1645
1719
|
/**
|
|
1646
1720
|
* Advance Harbor `/intents/{id}/fund` for x402 / USDC-on-Base intents.
|
|
1647
1721
|
*/
|
|
@@ -1715,6 +1789,12 @@ export class Paybond {
|
|
|
1715
1789
|
async aclose() {
|
|
1716
1790
|
await Promise.resolve();
|
|
1717
1791
|
}
|
|
1792
|
+
spendGuard(intentId, capabilityToken) {
|
|
1793
|
+
return new PaybondSpendGuard(new PaybondCapabilityBinding(this.harbor, intentId, capabilityToken));
|
|
1794
|
+
}
|
|
1795
|
+
async authorizeSpend(input) {
|
|
1796
|
+
return this.harbor.authorizeSpend(input);
|
|
1797
|
+
}
|
|
1718
1798
|
}
|
|
1719
1799
|
export { normalizeJson, jsonValueDigest } from "./json-digest.js";
|
|
1720
1800
|
export { buildSignedCreateIntentBody, intentCreationSignBytesRaw, } from "./principal-intent.js";
|
package/dist/init.d.ts
ADDED
package/dist/init.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const FRAMEWORKS = new Set([
|
|
3
|
+
"generic",
|
|
4
|
+
"provider-agnostic",
|
|
5
|
+
"openai-agents",
|
|
6
|
+
"claude",
|
|
7
|
+
"anthropic",
|
|
8
|
+
"gemini",
|
|
9
|
+
"google-ai",
|
|
10
|
+
"vercel-ai",
|
|
11
|
+
"langgraph",
|
|
12
|
+
"mcp",
|
|
13
|
+
]);
|
|
14
|
+
const FRAMEWORK_NOTES = {
|
|
15
|
+
generic: "Wrap the returned function around any side-effecting tool handler.",
|
|
16
|
+
"provider-agnostic": "Use the guarded handler with OpenAI, Gemini, Claude/Anthropic, local models, or any custom runtime.",
|
|
17
|
+
"openai-agents": "Register the guarded handler where your OpenAI Agents tool handler is defined.",
|
|
18
|
+
claude: "Call the guarded handler before the Claude tool-use action performs paid or external work.",
|
|
19
|
+
anthropic: "Call the guarded handler before the Anthropic tool-use action performs paid or external work.",
|
|
20
|
+
gemini: "Call the guarded handler before the Gemini function call performs paid or external work.",
|
|
21
|
+
"google-ai": "Call the guarded handler before the Google AI function call performs paid or external work.",
|
|
22
|
+
"vercel-ai": "Call the guarded handler from your Vercel AI SDK tool execute function.",
|
|
23
|
+
langgraph: "Call the guarded handler from the LangGraph JS node or tool wrapper that performs paid work.",
|
|
24
|
+
mcp: "Call the guarded handler inside the MCP tool implementation before paid or external work runs.",
|
|
25
|
+
};
|
|
26
|
+
function usage() {
|
|
27
|
+
return [
|
|
28
|
+
"Usage: paybond-init [--framework generic|provider-agnostic|openai-agents|claude|anthropic|gemini|google-ai|vercel-ai|langgraph|mcp] [--out paybond-spend-guard.ts] [--force]",
|
|
29
|
+
"",
|
|
30
|
+
"Scaffolds a Paybond spend guard wrapper for delegated agent spend controls.",
|
|
31
|
+
].join("\n");
|
|
32
|
+
}
|
|
33
|
+
function parseArgs(argv) {
|
|
34
|
+
let framework = "generic";
|
|
35
|
+
let out = "paybond-spend-guard.ts";
|
|
36
|
+
let force = false;
|
|
37
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
38
|
+
const arg = argv[i];
|
|
39
|
+
if (arg === "--help" || arg === "-h") {
|
|
40
|
+
process.stdout.write(`${usage()}\n`);
|
|
41
|
+
process.exitCode = 0;
|
|
42
|
+
return { framework, out, force };
|
|
43
|
+
}
|
|
44
|
+
if (arg === "--force") {
|
|
45
|
+
force = true;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (arg === "--framework") {
|
|
49
|
+
const raw = argv[i + 1];
|
|
50
|
+
i += 1;
|
|
51
|
+
if (!raw || !FRAMEWORKS.has(raw)) {
|
|
52
|
+
throw new Error("invalid --framework");
|
|
53
|
+
}
|
|
54
|
+
framework = raw;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (arg === "--out") {
|
|
58
|
+
const raw = argv[i + 1];
|
|
59
|
+
i += 1;
|
|
60
|
+
if (!raw || raw.startsWith("-")) {
|
|
61
|
+
throw new Error("invalid --out");
|
|
62
|
+
}
|
|
63
|
+
out = raw;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
67
|
+
}
|
|
68
|
+
return { framework, out, force };
|
|
69
|
+
}
|
|
70
|
+
function template(framework) {
|
|
71
|
+
return `import { Paybond, PaybondCapabilityBinding, PaybondSpendGuard } from "@paybond/kit";
|
|
72
|
+
|
|
73
|
+
type ToolInput = {
|
|
74
|
+
city: string;
|
|
75
|
+
maxPriceCents: number;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
async function bookHotel(input: ToolInput): Promise<{ confirmation: string }> {
|
|
79
|
+
// Put the side-effecting tool call here.
|
|
80
|
+
return { confirmation: \`demo-\${input.city}-\${input.maxPriceCents}\` };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function buildGuardedHotelTool(params: {
|
|
84
|
+
intentId: string;
|
|
85
|
+
capabilityToken: string;
|
|
86
|
+
}): Promise<(input: ToolInput) => Promise<{ confirmation: string }>> {
|
|
87
|
+
const paybond = await Paybond.open({
|
|
88
|
+
apiKey: process.env.PAYBOND_API_KEY!,
|
|
89
|
+
expectedEnvironment: "sandbox",
|
|
90
|
+
});
|
|
91
|
+
const binding = new PaybondCapabilityBinding(
|
|
92
|
+
paybond.harbor,
|
|
93
|
+
params.intentId,
|
|
94
|
+
params.capabilityToken,
|
|
95
|
+
);
|
|
96
|
+
const guard = new PaybondSpendGuard(binding);
|
|
97
|
+
|
|
98
|
+
// ${FRAMEWORK_NOTES[framework]}
|
|
99
|
+
return guard.guardTool(
|
|
100
|
+
{
|
|
101
|
+
operation: "travel.book_hotel",
|
|
102
|
+
requestedSpendCents: 20_000,
|
|
103
|
+
},
|
|
104
|
+
bookHotel,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
async function writeScaffold(out, body, force) {
|
|
110
|
+
// @ts-expect-error Node builtins are available in the published CLI runtime.
|
|
111
|
+
const fs = await import("node:fs/promises");
|
|
112
|
+
try {
|
|
113
|
+
await fs.stat(out);
|
|
114
|
+
if (!force) {
|
|
115
|
+
throw new Error(`${out} already exists; pass --force to overwrite`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
if (!(err && typeof err === "object" && "code" in err && err.code === "ENOENT")) {
|
|
120
|
+
if (!force) {
|
|
121
|
+
throw err;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await fs.writeFile(out, body, "utf8");
|
|
126
|
+
}
|
|
127
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
128
|
+
let parsed;
|
|
129
|
+
try {
|
|
130
|
+
parsed = parseArgs(argv);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n\n${usage()}\n`);
|
|
134
|
+
return 1;
|
|
135
|
+
}
|
|
136
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
await writeScaffold(parsed.out, template(parsed.framework), parsed.force);
|
|
140
|
+
process.stdout.write(`Created ${parsed.out}\n`);
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
main().then((code) => {
|
|
144
|
+
process.exitCode = code;
|
|
145
|
+
}, (err) => {
|
|
146
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
147
|
+
process.exitCode = 1;
|
|
148
|
+
});
|
package/dist/mcp-server.js
CHANGED
|
@@ -466,6 +466,27 @@ export class PaybondMCPServer {
|
|
|
466
466
|
: intArg(args.requested_spend_cents, "requested_spend_cents"),
|
|
467
467
|
}),
|
|
468
468
|
},
|
|
469
|
+
{
|
|
470
|
+
name: "paybond_authorize_agent_spend",
|
|
471
|
+
description: "Authorize delegated agent spend before a side-effecting tool, paid API, vendor action, or settlement workflow executes.",
|
|
472
|
+
inputSchema: objectSchema({
|
|
473
|
+
intent_id: { type: "string", description: "Canonical Harbor intent UUID." },
|
|
474
|
+
token: { type: "string", description: "Capability token to verify." },
|
|
475
|
+
operation: { type: "string", description: "Delegated operation or tool name." },
|
|
476
|
+
requested_spend_cents: {
|
|
477
|
+
type: "integer",
|
|
478
|
+
description: "Optional requested spend in cents for this tool call.",
|
|
479
|
+
},
|
|
480
|
+
}, ["intent_id", "token", "operation"]),
|
|
481
|
+
call: async (args) => this.runtime.verifyCapability({
|
|
482
|
+
intentId: uuidArg(args.intent_id, "intent_id"),
|
|
483
|
+
token: stringArg(args.token, "token"),
|
|
484
|
+
operation: stringArg(args.operation, "operation"),
|
|
485
|
+
requestedSpendCents: args.requested_spend_cents === undefined
|
|
486
|
+
? 0
|
|
487
|
+
: intArg(args.requested_spend_cents, "requested_spend_cents"),
|
|
488
|
+
}),
|
|
489
|
+
},
|
|
469
490
|
{
|
|
470
491
|
name: "paybond_list_intents",
|
|
471
492
|
description: "List tenant-scoped Harbor intents through the gateway operator view with optional filters.",
|
|
@@ -630,6 +651,20 @@ export class PaybondMCPServer {
|
|
|
630
651
|
idempotencyKey: optionalString(args.idempotency_key),
|
|
631
652
|
}),
|
|
632
653
|
},
|
|
654
|
+
{
|
|
655
|
+
name: "paybond_create_spend_intent",
|
|
656
|
+
description: "Create a signed Paybond spend intent through the gateway /harbor route. Use this when an agent workflow needs bounded budget, allowed operations, evidence, and settlement review.",
|
|
657
|
+
inputSchema: objectSchema({
|
|
658
|
+
body: { type: "object", additionalProperties: true },
|
|
659
|
+
recognition_proof: { type: "object", additionalProperties: true },
|
|
660
|
+
idempotency_key: { type: "string" },
|
|
661
|
+
}, ["body", "recognition_proof"]),
|
|
662
|
+
call: async (args) => this.runtime.createHarborIntent({
|
|
663
|
+
body: ensureObject(args.body, "body"),
|
|
664
|
+
recognitionProof: ensureObject(args.recognition_proof, "recognition_proof"),
|
|
665
|
+
idempotencyKey: optionalString(args.idempotency_key),
|
|
666
|
+
}),
|
|
667
|
+
},
|
|
633
668
|
{
|
|
634
669
|
name: "paybond_fund_intent",
|
|
635
670
|
description: "Advance Harbor funding through the gateway /harbor path with a replay-safe recognition proof.",
|
|
@@ -662,6 +697,22 @@ export class PaybondMCPServer {
|
|
|
662
697
|
idempotencyKey: optionalString(args.idempotency_key),
|
|
663
698
|
}),
|
|
664
699
|
},
|
|
700
|
+
{
|
|
701
|
+
name: "paybond_submit_spend_evidence",
|
|
702
|
+
description: "Submit signed evidence for a Paybond spend intent so release, refund, review, and receipt generation use the same audit-ready record.",
|
|
703
|
+
inputSchema: objectSchema({
|
|
704
|
+
intent_id: { type: "string" },
|
|
705
|
+
body: { type: "object", additionalProperties: true },
|
|
706
|
+
recognition_proof: { type: "object", additionalProperties: true },
|
|
707
|
+
idempotency_key: { type: "string" },
|
|
708
|
+
}, ["intent_id", "body", "recognition_proof"]),
|
|
709
|
+
call: async (args) => this.runtime.submitHarborEvidence({
|
|
710
|
+
intentId: uuidArg(args.intent_id, "intent_id"),
|
|
711
|
+
body: ensureObject(args.body, "body"),
|
|
712
|
+
recognitionProof: ensureObject(args.recognition_proof, "recognition_proof"),
|
|
713
|
+
idempotencyKey: optionalString(args.idempotency_key),
|
|
714
|
+
}),
|
|
715
|
+
},
|
|
665
716
|
{
|
|
666
717
|
name: "paybond_confirm_settlement",
|
|
667
718
|
description: "Confirm Harbor settlement through the gateway /harbor path with a replay-safe recognition proof.",
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paybond/kit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Paybond Kit for TypeScript: hosted Gateway sessions, capability verification, signed intent/evidence flows, and Stripe Connect or x402 / USDC-on-Base settlement.",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Paybond Kit for TypeScript: agent spend controls, hosted Gateway sessions, capability verification, signed intent/evidence flows, and Stripe Connect or x402 / USDC-on-Base settlement.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
|
+
"paybond-init": "dist/init.js",
|
|
10
11
|
"paybond-mcp-server": "dist/mcp-server.js"
|
|
11
12
|
},
|
|
12
13
|
"exports": {
|
|
@@ -41,6 +42,15 @@
|
|
|
41
42
|
"kit",
|
|
42
43
|
"agents",
|
|
43
44
|
"agent-runtime",
|
|
45
|
+
"agent-spend-controls",
|
|
46
|
+
"ai-agent-budget",
|
|
47
|
+
"delegated-spend",
|
|
48
|
+
"spend-guardrails",
|
|
49
|
+
"tool-call-spend-limits",
|
|
50
|
+
"openai-agents",
|
|
51
|
+
"gemini",
|
|
52
|
+
"claude",
|
|
53
|
+
"anthropic",
|
|
44
54
|
"agent-payments",
|
|
45
55
|
"escrow",
|
|
46
56
|
"intent-escrow",
|