@paybond/kit 0.9.2 → 0.9.4
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 +35 -18
- package/dist/index.d.ts +66 -0
- package/dist/index.js +206 -2
- package/dist/init.js +182 -54
- package/dist/login.d.ts +35 -0
- package/dist/login.js +435 -0
- package/dist/mcp-server.js +119 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -22,12 +22,24 @@ npm install @paybond/kit
|
|
|
22
22
|
- A `paybond_sk_sandbox_...` or `paybond_sk_live_...` service-account API key
|
|
23
23
|
- For intent creation or evidence submission: 32-byte Ed25519 signing seeds owned by your application
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Create a sandbox key for local development:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
|
|
28
|
+
npx -p @paybond/kit paybond login
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
+
`paybond login` writes `PAYBOND_API_KEY` to `.env.local` with file mode `0600`, refuses to overwrite an existing key unless `--force` is passed, and refuses env files that are not ignored by git. Live production keys are created by tenant admins in Console and stored in deployment secret managers.
|
|
32
|
+
|
|
33
|
+
## First guardrail scaffold
|
|
34
|
+
|
|
35
|
+
Use this first when you have a paid tool and want Paybond guardrails in the sandbox:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx -p @paybond/kit paybond-init --preset paid-tool-guard --framework provider-agnostic --out paybond-guardrail-demo.ts
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The generated demo opens Paybond, bootstraps a sandbox guardrail intent, wraps one replaceable paid-tool handler, submits sandbox evidence, and prints the lifecycle result. Free Developer is sandbox-only; live settlement rails start on paid production plans.
|
|
42
|
+
|
|
31
43
|
## Tenant isolation
|
|
32
44
|
|
|
33
45
|
Every session is bound to the tenant realm echoed by gateway-authenticated service-account introspection.
|
|
@@ -73,31 +85,34 @@ const paybond = await Paybond.open({
|
|
|
73
85
|
expectedEnvironment: "sandbox",
|
|
74
86
|
});
|
|
75
87
|
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
const guardrail = await paybond.guardrails.bootstrapSandbox({
|
|
89
|
+
operation: "travel.book_hotel",
|
|
90
|
+
requestedSpendCents: 20_000,
|
|
91
|
+
currency: "usd",
|
|
80
92
|
});
|
|
81
93
|
|
|
82
|
-
const
|
|
83
|
-
const capabilityToken = String(created.capability_token ?? "");
|
|
84
|
-
if (!capabilityToken) {
|
|
85
|
-
throw new Error("fund the intent before guarding tools");
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const guard = paybond.spendGuard(intentId, capabilityToken);
|
|
94
|
+
const guard = paybond.spendGuard(guardrail.intent_id, guardrail.capability_token);
|
|
89
95
|
const guardedTool = guard.guardTool(
|
|
90
|
-
{
|
|
96
|
+
{
|
|
97
|
+
operation: guardrail.operation,
|
|
98
|
+
requestedSpendCents: guardrail.requested_spend_cents,
|
|
99
|
+
},
|
|
91
100
|
async (input) => bookHotel(input),
|
|
92
101
|
);
|
|
102
|
+
|
|
103
|
+
const result = await guardedTool({ hotelId: "hotel_demo", maxPriceCents: 20_000 });
|
|
104
|
+
await paybond.guardrails.submitSandboxEvidence({
|
|
105
|
+
intentId: guardrail.intent_id,
|
|
106
|
+
payload: { result, sandbox: true },
|
|
107
|
+
});
|
|
93
108
|
```
|
|
94
109
|
|
|
95
|
-
The `paybond.harbor`
|
|
110
|
+
The `paybond.harbor` and `paybond.guardrails` clients are created by `Paybond.open(...)` and bound to the tenant resolved from the service-account API key. Production integrations read `capability_token` from `paybond.intents.create(...)`, or from `paybond.intents.fund(...)` after an `x402_usdc_base` payment challenge is satisfied.
|
|
96
111
|
|
|
97
|
-
Scaffold a
|
|
112
|
+
Scaffold a guardrail integration:
|
|
98
113
|
|
|
99
114
|
```bash
|
|
100
|
-
npx -p @paybond/kit paybond-init --framework provider-agnostic --out paybond-
|
|
115
|
+
npx -p @paybond/kit paybond-init --preset paid-tool-guard --framework provider-agnostic --out paybond-guardrail-demo.ts
|
|
101
116
|
```
|
|
102
117
|
|
|
103
118
|
## What the package includes
|
|
@@ -117,8 +132,9 @@ Gateway and trust helpers:
|
|
|
117
132
|
- `GatewaySignalClient` and `ServiceAccountSignalSession` for tenant-scoped Signal reads and signed portfolio artifacts
|
|
118
133
|
- `GatewayFraudClient` and `ServiceAccountFraudSession` for tenant-scoped fraud assessments, review queues, review events, metrics, and release-gate config
|
|
119
134
|
- Protocol-v2 helpers for mandate verification, replay-safe recognition proof verification, receipt reads, and A2A discovery
|
|
135
|
+
- `paybond login` for sandbox device approval and local `.env.local` API-key setup
|
|
120
136
|
- `paybond-mcp-server` for tenant-bound MCP tool exposure to any MCP-compatible host
|
|
121
|
-
- `paybond-init` for generating a
|
|
137
|
+
- `paybond-init` for generating a Paybond guardrail integration with a sandbox smoke path
|
|
122
138
|
|
|
123
139
|
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.
|
|
124
140
|
|
|
@@ -143,6 +159,7 @@ Gateway-backed protocol helpers throw `ProtocolHttpError` with parsed `errorCode
|
|
|
143
159
|
## Docs
|
|
144
160
|
|
|
145
161
|
- Long-form docs: https://paybond.ai/docs/kit
|
|
162
|
+
- One-command guardrails: https://paybond.ai/docs/kit/one-command-guardrails
|
|
146
163
|
- TypeScript quickstart: https://paybond.ai/docs/kit/quickstart-typescript
|
|
147
164
|
- TypeScript SDK reference: https://paybond.ai/docs/kit/sdk-reference-typescript
|
|
148
165
|
- MCP server guide: https://paybond.ai/docs/kit/mcp-server
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,49 @@ export type FundIntentResult = {
|
|
|
72
72
|
capabilityToken?: string;
|
|
73
73
|
funding?: IntentFundingResult;
|
|
74
74
|
};
|
|
75
|
+
export type SandboxGuardrailBootstrapInput = {
|
|
76
|
+
operation: string;
|
|
77
|
+
requestedSpendCents: number;
|
|
78
|
+
currency?: string;
|
|
79
|
+
evidenceSchema?: Record<string, unknown>;
|
|
80
|
+
metadata?: Record<string, unknown>;
|
|
81
|
+
idempotencyKey?: string;
|
|
82
|
+
};
|
|
83
|
+
export type SandboxGuardrailEvidenceInput = {
|
|
84
|
+
intentId: string;
|
|
85
|
+
payload?: Record<string, unknown>;
|
|
86
|
+
artifacts?: string[];
|
|
87
|
+
operation?: string;
|
|
88
|
+
requestedSpendCents?: number;
|
|
89
|
+
metadata?: Record<string, unknown>;
|
|
90
|
+
idempotencyKey?: string;
|
|
91
|
+
};
|
|
92
|
+
export type SandboxGuardrailBootstrapResult = {
|
|
93
|
+
tenant_id: string;
|
|
94
|
+
intent_id: string;
|
|
95
|
+
capability_token: string;
|
|
96
|
+
operation: string;
|
|
97
|
+
requested_spend_cents: number;
|
|
98
|
+
sandbox_lifecycle_status: string;
|
|
99
|
+
currency?: string;
|
|
100
|
+
settlement_rail?: string;
|
|
101
|
+
settlement_mode?: string;
|
|
102
|
+
simulator_event?: unknown;
|
|
103
|
+
};
|
|
104
|
+
export type SandboxGuardrailEvidenceResult = {
|
|
105
|
+
tenant_id: string;
|
|
106
|
+
intent_id: string;
|
|
107
|
+
capability_token?: string;
|
|
108
|
+
operation: string;
|
|
109
|
+
requested_spend_cents: number;
|
|
110
|
+
sandbox_lifecycle_status: string;
|
|
111
|
+
settlement_rail?: string;
|
|
112
|
+
settlement_mode?: string;
|
|
113
|
+
predicate_passed?: boolean | null;
|
|
114
|
+
payload_digest?: string;
|
|
115
|
+
artifacts_digest?: string;
|
|
116
|
+
simulator_event?: unknown;
|
|
117
|
+
};
|
|
75
118
|
export declare const DEFAULT_PAYBOND_GATEWAY_BASE_URL = "https://api.paybond.ai";
|
|
76
119
|
/** Async supplier for upstream Harbor bearer tokens on low-level direct clients. */
|
|
77
120
|
export type HarborBearerSupplier = () => Promise<string | null | undefined>;
|
|
@@ -878,6 +921,28 @@ export declare class GatewayHarborClient {
|
|
|
878
921
|
}): Promise<FundIntentResult>;
|
|
879
922
|
submitEvidence(intentId: string, evidenceBody: Record<string, unknown>, options: GatewayHarborMutationOptions): Promise<SubmitEvidenceResult>;
|
|
880
923
|
}
|
|
924
|
+
type GatewaySandboxGuardrailsClientOptions = {
|
|
925
|
+
staticGatewayBearerToken: string;
|
|
926
|
+
maxRetries?: number;
|
|
927
|
+
};
|
|
928
|
+
/**
|
|
929
|
+
* Gateway sandbox guardrail helpers.
|
|
930
|
+
*
|
|
931
|
+
* These routes derive tenant scope only from the service-account bearer token and intentionally
|
|
932
|
+
* reject caller-supplied tenant IDs, including the normal `x-tenant-id` Gateway Harbor header.
|
|
933
|
+
*/
|
|
934
|
+
export declare class PaybondGuardrails {
|
|
935
|
+
private readonly base;
|
|
936
|
+
readonly tenantId: string;
|
|
937
|
+
private readonly bearerToken;
|
|
938
|
+
private readonly maxRetries;
|
|
939
|
+
constructor(gatewayBaseUrl: string, tenantId: string, options: GatewaySandboxGuardrailsClientOptions);
|
|
940
|
+
private headers;
|
|
941
|
+
private fetchWithRetries;
|
|
942
|
+
private postJSON;
|
|
943
|
+
bootstrapSandbox(input: SandboxGuardrailBootstrapInput): Promise<SandboxGuardrailBootstrapResult>;
|
|
944
|
+
submitSandboxEvidence(input: SandboxGuardrailEvidenceInput): Promise<SandboxGuardrailEvidenceResult>;
|
|
945
|
+
}
|
|
881
946
|
type GatewaySignalClientOptions = {
|
|
882
947
|
staticGatewayBearerToken: string;
|
|
883
948
|
maxRetries?: number;
|
|
@@ -1071,6 +1136,7 @@ export declare class PaybondIntents {
|
|
|
1071
1136
|
*/
|
|
1072
1137
|
export declare class Paybond {
|
|
1073
1138
|
readonly harbor: GatewayHarborClient;
|
|
1139
|
+
readonly guardrails: PaybondGuardrails;
|
|
1074
1140
|
readonly signal: GatewaySignalClient;
|
|
1075
1141
|
readonly fraud: GatewayFraudClient;
|
|
1076
1142
|
readonly a2a: GatewayA2AClient;
|
package/dist/index.js
CHANGED
|
@@ -801,6 +801,132 @@ export class GatewayHarborClient {
|
|
|
801
801
|
return parseSubmitEvidenceResponse(JSON.parse(text));
|
|
802
802
|
}
|
|
803
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* Gateway sandbox guardrail helpers.
|
|
806
|
+
*
|
|
807
|
+
* These routes derive tenant scope only from the service-account bearer token and intentionally
|
|
808
|
+
* reject caller-supplied tenant IDs, including the normal `x-tenant-id` Gateway Harbor header.
|
|
809
|
+
*/
|
|
810
|
+
export class PaybondGuardrails {
|
|
811
|
+
base;
|
|
812
|
+
tenantId;
|
|
813
|
+
bearerToken;
|
|
814
|
+
maxRetries;
|
|
815
|
+
constructor(gatewayBaseUrl, tenantId, options) {
|
|
816
|
+
this.base = normalizeBase(gatewayBaseUrl) + "/";
|
|
817
|
+
this.tenantId = tenantId.trim();
|
|
818
|
+
this.bearerToken = options.staticGatewayBearerToken.trim();
|
|
819
|
+
this.maxRetries = Math.max(1, options.maxRetries ?? 3);
|
|
820
|
+
}
|
|
821
|
+
headers(extra) {
|
|
822
|
+
const headers = new Headers(extra);
|
|
823
|
+
headers.set("accept", "application/json");
|
|
824
|
+
headers.set("authorization", `Bearer ${this.bearerToken}`);
|
|
825
|
+
return headers;
|
|
826
|
+
}
|
|
827
|
+
async fetchWithRetries(url, init) {
|
|
828
|
+
let lastErr;
|
|
829
|
+
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
|
|
830
|
+
let res;
|
|
831
|
+
try {
|
|
832
|
+
res = await fetch(url, init);
|
|
833
|
+
}
|
|
834
|
+
catch (e) {
|
|
835
|
+
lastErr = e;
|
|
836
|
+
if (attempt + 1 >= this.maxRetries)
|
|
837
|
+
throw e;
|
|
838
|
+
await new Promise((r) => setTimeout(r, backoffMs(attempt)));
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
if ([429, 500, 502, 503, 504].includes(res.status) && attempt + 1 < this.maxRetries) {
|
|
842
|
+
const raSec = parseRetryAfterSeconds(res.headers.get("retry-after"));
|
|
843
|
+
const delayMs = raSec != null ? raSec * 1000 : backoffMs(attempt);
|
|
844
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
return res;
|
|
848
|
+
}
|
|
849
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
850
|
+
}
|
|
851
|
+
async postJSON(path, payload, options) {
|
|
852
|
+
const url = `${this.base}${path.replace(/^\/+/, "")}`;
|
|
853
|
+
const extraHeaders = {
|
|
854
|
+
"content-type": "application/json",
|
|
855
|
+
};
|
|
856
|
+
if (options?.idempotencyKey?.trim()) {
|
|
857
|
+
extraHeaders["idempotency-key"] = options.idempotencyKey.trim();
|
|
858
|
+
}
|
|
859
|
+
const res = await this.fetchWithRetries(url, {
|
|
860
|
+
method: "POST",
|
|
861
|
+
headers: this.headers(extraHeaders),
|
|
862
|
+
body: JSON.stringify(payload),
|
|
863
|
+
});
|
|
864
|
+
const text = await res.text();
|
|
865
|
+
return { res, text, url };
|
|
866
|
+
}
|
|
867
|
+
async bootstrapSandbox(input) {
|
|
868
|
+
const payload = {
|
|
869
|
+
operation: input.operation,
|
|
870
|
+
requested_spend_cents: input.requestedSpendCents,
|
|
871
|
+
};
|
|
872
|
+
if (input.currency !== undefined) {
|
|
873
|
+
payload.currency = input.currency;
|
|
874
|
+
}
|
|
875
|
+
if (input.evidenceSchema !== undefined) {
|
|
876
|
+
payload.evidence_schema = input.evidenceSchema;
|
|
877
|
+
}
|
|
878
|
+
if (input.metadata !== undefined) {
|
|
879
|
+
payload.metadata = input.metadata;
|
|
880
|
+
}
|
|
881
|
+
const { res, text, url } = await this.postJSON("/v1/sandbox/guardrails/bootstrap", payload, { idempotencyKey: input.idempotencyKey });
|
|
882
|
+
if (!res.ok) {
|
|
883
|
+
throw new HarborHttpError(`Gateway sandbox guardrail bootstrap HTTP ${res.status}: ${text}`, {
|
|
884
|
+
statusCode: res.status,
|
|
885
|
+
url,
|
|
886
|
+
bodyText: text,
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
return parseSandboxGuardrailBootstrapResponse(JSON.parse(text), {
|
|
890
|
+
tenantId: this.tenantId,
|
|
891
|
+
url,
|
|
892
|
+
bodyText: text,
|
|
893
|
+
statusCode: res.status,
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
async submitSandboxEvidence(input) {
|
|
897
|
+
const payload = {};
|
|
898
|
+
if (input.payload !== undefined) {
|
|
899
|
+
payload.payload = input.payload;
|
|
900
|
+
}
|
|
901
|
+
if (input.artifacts !== undefined) {
|
|
902
|
+
payload.artifacts = input.artifacts;
|
|
903
|
+
}
|
|
904
|
+
if (input.operation !== undefined) {
|
|
905
|
+
payload.operation = input.operation;
|
|
906
|
+
}
|
|
907
|
+
if (input.requestedSpendCents !== undefined) {
|
|
908
|
+
payload.requested_spend_cents = input.requestedSpendCents;
|
|
909
|
+
}
|
|
910
|
+
if (input.metadata !== undefined) {
|
|
911
|
+
payload.metadata = input.metadata;
|
|
912
|
+
}
|
|
913
|
+
const { res, text, url } = await this.postJSON(`/v1/sandbox/guardrails/${encodeURIComponent(input.intentId)}/evidence`, payload, { idempotencyKey: input.idempotencyKey });
|
|
914
|
+
if (!res.ok) {
|
|
915
|
+
throw new HarborHttpError(`Gateway sandbox guardrail evidence HTTP ${res.status}: ${text}`, {
|
|
916
|
+
statusCode: res.status,
|
|
917
|
+
url,
|
|
918
|
+
bodyText: text,
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
return parseSandboxGuardrailEvidenceResponse(JSON.parse(text), {
|
|
922
|
+
tenantId: this.tenantId,
|
|
923
|
+
intentId: input.intentId,
|
|
924
|
+
url,
|
|
925
|
+
bodyText: text,
|
|
926
|
+
statusCode: res.status,
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
804
930
|
const DEFAULT_PRINCIPAL_PATH = "/v1/auth/principal";
|
|
805
931
|
const SETTLEMENT_RAIL_VALUES = new Set(["stripe_connect", "stripe_ach_debit", "x402_usdc_base"]);
|
|
806
932
|
const FRAUD_REVIEW_EVENT_TYPES = new Set([
|
|
@@ -878,6 +1004,78 @@ function parseSubmitEvidenceResponse(value) {
|
|
|
878
1004
|
predicatePassed: typeof body.predicate_passed === "boolean" ? body.predicate_passed : undefined,
|
|
879
1005
|
};
|
|
880
1006
|
}
|
|
1007
|
+
function parseSandboxGuardrailBootstrapResponse(value, init) {
|
|
1008
|
+
const body = assertJSONObject(value);
|
|
1009
|
+
const tenant = sandboxGuardrailString(body, "tenant_id", init);
|
|
1010
|
+
if (tenant !== init.tenantId) {
|
|
1011
|
+
throw new Error(`sandbox guardrail tenant mismatch: client=${init.tenantId} gateway=${tenant}`);
|
|
1012
|
+
}
|
|
1013
|
+
return {
|
|
1014
|
+
tenant_id: tenant,
|
|
1015
|
+
intent_id: sandboxGuardrailString(body, "intent_id", init),
|
|
1016
|
+
capability_token: sandboxGuardrailString(body, "capability_token", init),
|
|
1017
|
+
operation: sandboxGuardrailString(body, "operation", init),
|
|
1018
|
+
requested_spend_cents: sandboxGuardrailNumber(body, "requested_spend_cents", init),
|
|
1019
|
+
sandbox_lifecycle_status: sandboxGuardrailString(body, "sandbox_lifecycle_status", init),
|
|
1020
|
+
currency: sandboxGuardrailOptionalString(body.currency),
|
|
1021
|
+
settlement_rail: sandboxGuardrailOptionalString(body.settlement_rail),
|
|
1022
|
+
settlement_mode: sandboxGuardrailOptionalString(body.settlement_mode),
|
|
1023
|
+
simulator_event: body.simulator_event,
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
function parseSandboxGuardrailEvidenceResponse(value, init) {
|
|
1027
|
+
const body = assertJSONObject(value);
|
|
1028
|
+
const tenant = sandboxGuardrailString(body, "tenant_id", init);
|
|
1029
|
+
if (tenant !== init.tenantId) {
|
|
1030
|
+
throw new Error(`sandbox guardrail tenant mismatch: client=${init.tenantId} gateway=${tenant}`);
|
|
1031
|
+
}
|
|
1032
|
+
const intentId = sandboxGuardrailString(body, "intent_id", init);
|
|
1033
|
+
if (intentId !== init.intentId) {
|
|
1034
|
+
throw new Error(`sandbox guardrail intent mismatch: requested=${init.intentId} gateway=${intentId}`);
|
|
1035
|
+
}
|
|
1036
|
+
const predicatePassedRaw = body.predicate_passed;
|
|
1037
|
+
return {
|
|
1038
|
+
tenant_id: tenant,
|
|
1039
|
+
intent_id: intentId,
|
|
1040
|
+
capability_token: sandboxGuardrailOptionalString(body.capability_token),
|
|
1041
|
+
operation: sandboxGuardrailString(body, "operation", init),
|
|
1042
|
+
requested_spend_cents: sandboxGuardrailNumber(body, "requested_spend_cents", init),
|
|
1043
|
+
sandbox_lifecycle_status: sandboxGuardrailString(body, "sandbox_lifecycle_status", init),
|
|
1044
|
+
settlement_rail: sandboxGuardrailOptionalString(body.settlement_rail),
|
|
1045
|
+
settlement_mode: sandboxGuardrailOptionalString(body.settlement_mode),
|
|
1046
|
+
predicate_passed: typeof predicatePassedRaw === "boolean" || predicatePassedRaw === null
|
|
1047
|
+
? predicatePassedRaw
|
|
1048
|
+
: undefined,
|
|
1049
|
+
payload_digest: sandboxGuardrailOptionalString(body.payload_digest),
|
|
1050
|
+
artifacts_digest: sandboxGuardrailOptionalString(body.artifacts_digest),
|
|
1051
|
+
simulator_event: body.simulator_event,
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
function sandboxGuardrailString(body, field, init) {
|
|
1055
|
+
const value = body[field];
|
|
1056
|
+
if (typeof value === "string" && value.trim()) {
|
|
1057
|
+
return value;
|
|
1058
|
+
}
|
|
1059
|
+
throw new HarborHttpError(`Gateway sandbox guardrail response missing ${field}`, {
|
|
1060
|
+
statusCode: init.statusCode,
|
|
1061
|
+
url: init.url,
|
|
1062
|
+
bodyText: init.bodyText,
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
function sandboxGuardrailOptionalString(value) {
|
|
1066
|
+
return typeof value === "string" && value.trim() ? value : undefined;
|
|
1067
|
+
}
|
|
1068
|
+
function sandboxGuardrailNumber(body, field, init) {
|
|
1069
|
+
const value = body[field];
|
|
1070
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1071
|
+
return value;
|
|
1072
|
+
}
|
|
1073
|
+
throw new HarborHttpError(`Gateway sandbox guardrail response missing ${field}`, {
|
|
1074
|
+
statusCode: init.statusCode,
|
|
1075
|
+
url: init.url,
|
|
1076
|
+
bodyText: init.bodyText,
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
881
1079
|
function parseIntentFundingResult(value) {
|
|
882
1080
|
const body = assertJSONObject(value);
|
|
883
1081
|
const onchainRaw = body.onchain_transaction_hashes;
|
|
@@ -1795,13 +1993,15 @@ export class PaybondIntents {
|
|
|
1795
1993
|
*/
|
|
1796
1994
|
export class Paybond {
|
|
1797
1995
|
harbor;
|
|
1996
|
+
guardrails;
|
|
1798
1997
|
signal;
|
|
1799
1998
|
fraud;
|
|
1800
1999
|
a2a;
|
|
1801
2000
|
protocol;
|
|
1802
2001
|
intents;
|
|
1803
|
-
constructor(harbor, signal, fraud, a2a, protocol) {
|
|
2002
|
+
constructor(harbor, guardrails, signal, fraud, a2a, protocol) {
|
|
1804
2003
|
this.harbor = harbor;
|
|
2004
|
+
this.guardrails = guardrails;
|
|
1805
2005
|
this.signal = signal;
|
|
1806
2006
|
this.fraud = fraud;
|
|
1807
2007
|
this.a2a = a2a;
|
|
@@ -1817,6 +2017,10 @@ export class Paybond {
|
|
|
1817
2017
|
staticGatewayBearerToken: init.apiKey,
|
|
1818
2018
|
maxRetries,
|
|
1819
2019
|
});
|
|
2020
|
+
const guardrails = new PaybondGuardrails(gatewayBaseUrl, tenantId, {
|
|
2021
|
+
staticGatewayBearerToken: init.apiKey,
|
|
2022
|
+
maxRetries,
|
|
2023
|
+
});
|
|
1820
2024
|
const signal = new GatewaySignalClient(gatewayBaseUrl, tenantId, {
|
|
1821
2025
|
staticGatewayBearerToken: init.apiKey,
|
|
1822
2026
|
maxRetries,
|
|
@@ -1833,7 +2037,7 @@ export class Paybond {
|
|
|
1833
2037
|
staticGatewayBearerToken: init.apiKey,
|
|
1834
2038
|
maxRetries,
|
|
1835
2039
|
});
|
|
1836
|
-
return new Paybond(harbor, signal, fraud, a2a, protocol);
|
|
2040
|
+
return new Paybond(harbor, guardrails, signal, fraud, a2a, protocol);
|
|
1837
2041
|
}
|
|
1838
2042
|
/** Reserved for future HTTP client cleanup; safe to call after work completes. */
|
|
1839
2043
|
async aclose() {
|