@paybond/kit 0.4.0 → 0.5.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 +71 -26
- package/dist/index.d.ts +235 -0
- package/dist/index.js +317 -2
- package/dist/mcp-server.js +31 -2
- package/package.json +12 -3
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# `@paybond/kit`
|
|
2
2
|
|
|
3
|
-
Paybond Kit for TypeScript
|
|
3
|
+
Paybond Kit for TypeScript is the npm package for tenant-bound Paybond integrations. It opens gateway-authenticated Harbor sessions, verifies capability tokens, signs intent and evidence payloads, funds x402 / USDC-on-Base intents, and reads tenant-scoped Signal, fraud, ledger, protocol, and A2A data.
|
|
4
4
|
|
|
5
|
-
Install
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @paybond/kit
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
`@paybond/kit` is an ESM-only package for modern Node.js runtimes. Use `import` from a Node ESM / `NodeNext` project or a compatible bundler.
|
|
12
|
+
|
|
11
13
|
## Open source
|
|
12
14
|
|
|
13
15
|
`@paybond/kit` is distributed as open-source software under the Apache 2.0 license. The published npm package includes the full license text in `LICENSE`.
|
|
@@ -17,6 +19,23 @@ npm install @paybond/kit
|
|
|
17
19
|
- Node.js 22+
|
|
18
20
|
- A `paybond_sk_...` service-account API key
|
|
19
21
|
- Reachable Gateway and Harbor base URLs
|
|
22
|
+
- For capability verification: a funded intent id and a capability token minted for that intent
|
|
23
|
+
- For intent creation or evidence submission: 32-byte Ed25519 signing seeds owned by your application
|
|
24
|
+
|
|
25
|
+
Minimal environment for the quick start:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export PAYBOND_GATEWAY_URL="https://gateway.example.com"
|
|
29
|
+
export PAYBOND_HARBOR_URL="https://harbor.example.com"
|
|
30
|
+
export PAYBOND_API_KEY="paybond_sk_..."
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Optional, if you want the quick start to verify a capability:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
export PAYBOND_INTENT_ID="00000000-0000-0000-0000-000000000000"
|
|
37
|
+
export PAYBOND_CAPABILITY="base64-biscuit-token"
|
|
38
|
+
```
|
|
20
39
|
|
|
21
40
|
## Tenant isolation
|
|
22
41
|
|
|
@@ -31,22 +50,37 @@ Every session is bound to the tenant realm echoed by gateway-authenticated servi
|
|
|
31
50
|
```ts
|
|
32
51
|
import { Paybond } from "@paybond/kit";
|
|
33
52
|
|
|
53
|
+
function requiredEnv(name: string): string {
|
|
54
|
+
const value = process.env[name];
|
|
55
|
+
if (!value) {
|
|
56
|
+
throw new Error(`missing ${name}`);
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
34
61
|
const paybond = await Paybond.open({
|
|
35
|
-
gatewayBaseUrl: "
|
|
36
|
-
apiKey:
|
|
37
|
-
harborBaseUrl: "
|
|
62
|
+
gatewayBaseUrl: requiredEnv("PAYBOND_GATEWAY_URL"),
|
|
63
|
+
apiKey: requiredEnv("PAYBOND_API_KEY"),
|
|
64
|
+
harborBaseUrl: requiredEnv("PAYBOND_HARBOR_URL"),
|
|
38
65
|
});
|
|
39
66
|
|
|
40
67
|
try {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
console.log("tenant realm:", paybond.harbor.tenantId);
|
|
69
|
+
|
|
70
|
+
const intentId = process.env.PAYBOND_INTENT_ID;
|
|
71
|
+
const capability = process.env.PAYBOND_CAPABILITY;
|
|
72
|
+
if (intentId && capability) {
|
|
73
|
+
const verified = await paybond.harbor.verifyCapability({
|
|
74
|
+
intentId,
|
|
75
|
+
token: capability,
|
|
76
|
+
operation: "payments.capture",
|
|
77
|
+
requestedSpendCents: 18_700,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (!verified.allow) {
|
|
81
|
+
throw new Error(`verify denied: ${verified.code ?? "deny"} ${verified.message ?? ""}`);
|
|
82
|
+
}
|
|
83
|
+
console.log("capability verified:", verified.auditId);
|
|
50
84
|
}
|
|
51
85
|
} finally {
|
|
52
86
|
await paybond.aclose();
|
|
@@ -55,14 +89,25 @@ try {
|
|
|
55
89
|
|
|
56
90
|
## What the package includes
|
|
57
91
|
|
|
92
|
+
Core SDK:
|
|
93
|
+
|
|
58
94
|
- `Paybond.open(...)` for gateway-authenticated, tenant-derived Harbor sessions
|
|
59
95
|
- `HarborClient` for capability verification, intent creation, x402 funding, evidence submission, and ledger reads
|
|
60
|
-
-
|
|
61
|
-
- `GatewaySignalClient` and `ServiceAccountSignalSession` for tenant-scoped Signal reads and signed portfolio artifacts
|
|
62
|
-
- `paybond.signal` on `Paybond` sessions opened from one service-account API key
|
|
96
|
+
- `paybond.signal` and `paybond.fraud` on `Paybond` sessions opened from one service-account API key
|
|
63
97
|
- `PaybondIntents` helpers for principal-signed intent creation, x402 funding, and payee-signed evidence submission
|
|
98
|
+
|
|
99
|
+
Gateway and trust helpers:
|
|
100
|
+
|
|
101
|
+
- `GatewaySignalClient` and `ServiceAccountSignalSession` for tenant-scoped Signal reads and signed portfolio artifacts
|
|
102
|
+
- `GatewayFraudClient` and `ServiceAccountFraudSession` for tenant-scoped fraud assessments, review queues, review events, metrics, and release-gate config
|
|
103
|
+
- Protocol-v2 helpers for mandate verification, replay-safe recognition proof verification, receipt reads, and A2A discovery
|
|
64
104
|
- `paybond-mcp-server` for tenant-bound MCP tool exposure to any MCP-compatible host
|
|
65
|
-
|
|
105
|
+
|
|
106
|
+
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.
|
|
107
|
+
|
|
108
|
+
Advanced exports:
|
|
109
|
+
|
|
110
|
+
- Low-level signing helpers for callers that need to pre-build signed request bodies or evidence payloads
|
|
66
111
|
|
|
67
112
|
`allowedTools` values are your own tool or operation names, not a Paybond-owned catalog. Harbor enforces string matching against whatever names you chose when creating the intent.
|
|
68
113
|
|
|
@@ -75,21 +120,21 @@ Gateway-backed protocol helpers throw `ProtocolHttpError` with parsed `errorCode
|
|
|
75
120
|
## What it does not include
|
|
76
121
|
|
|
77
122
|
- No operator-tier settlement or console workflows
|
|
123
|
+
- No model-provider-specific TypeScript agent wrapper; use the documented app-side wrapper pattern with `PaybondCapabilityBinding`
|
|
78
124
|
- No model-provider-specific MCP wrapper; the MCP server is host-agnostic and works with any MCP-compatible runtime
|
|
79
125
|
|
|
80
126
|
## Docs
|
|
81
127
|
|
|
82
|
-
- Long-form docs:
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
- OpenAI Agents example: `examples/paybond-kit-openai-agents-typescript/`
|
|
128
|
+
- Long-form docs: https://paybond.ai/docs/kit
|
|
129
|
+
- TypeScript quickstart: https://paybond.ai/docs/kit/quickstart-typescript
|
|
130
|
+
- TypeScript SDK reference: https://paybond.ai/docs/kit/sdk-reference-typescript
|
|
131
|
+
- MCP server guide: https://paybond.ai/docs/kit/mcp-server
|
|
132
|
+
- Agent runtime tutorial: https://paybond.ai/docs/kit/agent-runtime-tutorial
|
|
133
|
+
- TypeScript example projects: https://paybond.ai/docs/kit/examples-typescript
|
|
89
134
|
|
|
90
135
|
## Release verification
|
|
91
136
|
|
|
92
|
-
|
|
137
|
+
For maintainers working from a source checkout, release verification lives in this package directory:
|
|
93
138
|
|
|
94
139
|
```bash
|
|
95
140
|
npm run verify:release
|
package/dist/index.d.ts
CHANGED
|
@@ -199,6 +199,198 @@ export type SignalPortfolioSummary = {
|
|
|
199
199
|
total_receipted_volume_cents: number;
|
|
200
200
|
operators_under_review: number;
|
|
201
201
|
};
|
|
202
|
+
export type SignalFraudSeverity = "elevated" | "high" | "critical";
|
|
203
|
+
export type SignalReviewState = "none" | "open" | "in_review" | "closed" | "all";
|
|
204
|
+
export type SignalFraudSignal = {
|
|
205
|
+
code: string;
|
|
206
|
+
severity: SignalFraudSeverity | string;
|
|
207
|
+
category: string;
|
|
208
|
+
window: string;
|
|
209
|
+
evidence_count: number;
|
|
210
|
+
summary: string;
|
|
211
|
+
affects_score: false;
|
|
212
|
+
signal_source?: string;
|
|
213
|
+
first_seen_at?: string;
|
|
214
|
+
last_seen_at?: string;
|
|
215
|
+
evidence_binding_strength?: string;
|
|
216
|
+
provider_event_refs?: string[];
|
|
217
|
+
intent_refs?: string[];
|
|
218
|
+
};
|
|
219
|
+
export type SignalFraudAssessment = {
|
|
220
|
+
fraud_signal_version: string;
|
|
221
|
+
level: "none" | SignalFraudSeverity | string;
|
|
222
|
+
highest_severity: "none" | SignalFraudSeverity | string;
|
|
223
|
+
review_priority: "normal" | "elevated" | "high" | "urgent" | string;
|
|
224
|
+
signal_count: number;
|
|
225
|
+
severe_signal_count: number;
|
|
226
|
+
summary: string;
|
|
227
|
+
};
|
|
228
|
+
export type SignalFraudReleaseGateMode = "review_only" | "critical_hold";
|
|
229
|
+
export type SignalFraudReleaseGateConfig = {
|
|
230
|
+
mode: SignalFraudReleaseGateMode | string;
|
|
231
|
+
};
|
|
232
|
+
export type SignalFraudSignalFamilyReliability = {
|
|
233
|
+
signal_family: string;
|
|
234
|
+
reliable: boolean;
|
|
235
|
+
stale: boolean;
|
|
236
|
+
sparse: boolean;
|
|
237
|
+
reviewed_count: number;
|
|
238
|
+
labeled_outcome_count: number;
|
|
239
|
+
review_precision_bps: number;
|
|
240
|
+
min_signal_family_labeled_outcome_count: number;
|
|
241
|
+
last_labeled_at?: string;
|
|
242
|
+
reasons: string[];
|
|
243
|
+
summary: string;
|
|
244
|
+
};
|
|
245
|
+
export type SignalFraudReleaseGateMetricsReliability = {
|
|
246
|
+
reliable: boolean;
|
|
247
|
+
stale: boolean;
|
|
248
|
+
sparse: boolean;
|
|
249
|
+
reviewed_count: number;
|
|
250
|
+
labeled_outcome_count: number;
|
|
251
|
+
review_precision_bps: number;
|
|
252
|
+
min_reviewed_count: number;
|
|
253
|
+
min_labeled_outcome_count: number;
|
|
254
|
+
min_signal_family_labeled_outcome_count: number;
|
|
255
|
+
min_review_precision_bps: number;
|
|
256
|
+
last_labeled_at?: string;
|
|
257
|
+
signal_families?: SignalFraudSignalFamilyReliability[];
|
|
258
|
+
reasons: string[];
|
|
259
|
+
summary: string;
|
|
260
|
+
};
|
|
261
|
+
export type SignalFraudReleaseGateDecision = {
|
|
262
|
+
mode: SignalFraudReleaseGateMode | string;
|
|
263
|
+
enforcement_enabled: boolean;
|
|
264
|
+
metrics_reliable: boolean;
|
|
265
|
+
release_allowed: boolean;
|
|
266
|
+
hold_required: boolean;
|
|
267
|
+
critical_signal_count: number;
|
|
268
|
+
critical_signal_codes: string[];
|
|
269
|
+
blocking_signal_codes?: string[];
|
|
270
|
+
blocking_evidence_refs?: string[];
|
|
271
|
+
reliability_reasons?: string[];
|
|
272
|
+
reasons: string[];
|
|
273
|
+
summary: string;
|
|
274
|
+
};
|
|
275
|
+
export type SignalFraudAssessmentResponse = {
|
|
276
|
+
schema_version: number;
|
|
277
|
+
tenant_id: string;
|
|
278
|
+
operator_did: string;
|
|
279
|
+
score_model_version: string;
|
|
280
|
+
review_state: string;
|
|
281
|
+
review_outcome: string;
|
|
282
|
+
review_reasons: string[];
|
|
283
|
+
fraud_signals: SignalFraudSignal[];
|
|
284
|
+
fraud_assessment: SignalFraudAssessment;
|
|
285
|
+
release_gate?: SignalFraudReleaseGateDecision;
|
|
286
|
+
[key: string]: unknown;
|
|
287
|
+
};
|
|
288
|
+
export type SignalFraudReviewQueueItem = {
|
|
289
|
+
operator_did: string;
|
|
290
|
+
review_state: string;
|
|
291
|
+
review_outcome: string;
|
|
292
|
+
review_reasons: string[];
|
|
293
|
+
anomaly_flagged: boolean;
|
|
294
|
+
opened_at: string;
|
|
295
|
+
reviewed_at: string;
|
|
296
|
+
updated_at: string;
|
|
297
|
+
last_receipt_message_digest_hex: string;
|
|
298
|
+
fraud_signals: SignalFraudSignal[];
|
|
299
|
+
fraud_assessment: SignalFraudAssessment;
|
|
300
|
+
release_gate?: SignalFraudReleaseGateDecision;
|
|
301
|
+
[key: string]: unknown;
|
|
302
|
+
};
|
|
303
|
+
export type SignalFraudReviewQueueResponse = {
|
|
304
|
+
schema_version: number;
|
|
305
|
+
tenant_id: string;
|
|
306
|
+
score_model_version: string;
|
|
307
|
+
items: SignalFraudReviewQueueItem[];
|
|
308
|
+
};
|
|
309
|
+
export type SignalFraudMetricsWindow = "24h" | "7d" | "30d";
|
|
310
|
+
export type SignalFraudMetricsResponse = {
|
|
311
|
+
schema_version: number;
|
|
312
|
+
tenant_id: string;
|
|
313
|
+
score_model_version: string;
|
|
314
|
+
fraud_signal_version: string;
|
|
315
|
+
window: SignalFraudMetricsWindow | string;
|
|
316
|
+
window_started_at: string;
|
|
317
|
+
window_ended_at: string;
|
|
318
|
+
generated_at: string;
|
|
319
|
+
flagged_operator_count: number;
|
|
320
|
+
critical_signal_count: number;
|
|
321
|
+
high_signal_count: number;
|
|
322
|
+
elevated_signal_count: number;
|
|
323
|
+
review_open_count: number;
|
|
324
|
+
review_load_count: number;
|
|
325
|
+
reviewed_count: number;
|
|
326
|
+
labeled_outcome_count: number;
|
|
327
|
+
confirmed_risk_count: number;
|
|
328
|
+
false_positive_count: number;
|
|
329
|
+
needs_more_evidence_count: number;
|
|
330
|
+
review_precision_bps: number;
|
|
331
|
+
false_positive_rate_bps: number;
|
|
332
|
+
confirmed_risk_rate_bps: number;
|
|
333
|
+
labeled_coverage_bps: number;
|
|
334
|
+
median_time_to_review_seconds: number;
|
|
335
|
+
refund_burst_count: number;
|
|
336
|
+
dispute_cluster_count: number;
|
|
337
|
+
replay_appeal_abuse_count: number;
|
|
338
|
+
critical_signal_hold_candidate_count: number;
|
|
339
|
+
provider_signal_count: number;
|
|
340
|
+
stale_label_gap_seconds: number;
|
|
341
|
+
stale_signal_family_label_gap_count: number;
|
|
342
|
+
backtest_summary: string;
|
|
343
|
+
release_gate_config?: SignalFraudReleaseGateConfig;
|
|
344
|
+
release_gate_metrics_reliability?: SignalFraudReleaseGateMetricsReliability;
|
|
345
|
+
};
|
|
346
|
+
export type SignalFraudReleaseGateConfigResponse = {
|
|
347
|
+
schema_version: number;
|
|
348
|
+
tenant_id: string;
|
|
349
|
+
score_model_version: string;
|
|
350
|
+
fraud_signal_version: string;
|
|
351
|
+
generated_at: string;
|
|
352
|
+
config: SignalFraudReleaseGateConfig;
|
|
353
|
+
metrics_reliability: SignalFraudReleaseGateMetricsReliability;
|
|
354
|
+
};
|
|
355
|
+
export type SignalFraudReviewEventType = "review_open_requested" | "appeal_requested" | "replay_requested" | "review_outcome_recorded" | SignalFraudReviewOutcome;
|
|
356
|
+
export type SignalFraudReviewOutcome = "confirmed_risk" | "false_positive" | "needs_more_evidence";
|
|
357
|
+
export type SignalFraudReviewEventInput = {
|
|
358
|
+
eventType: SignalFraudReviewEventType | string;
|
|
359
|
+
reviewOutcome?: SignalFraudReviewOutcome | string;
|
|
360
|
+
review_outcome?: SignalFraudReviewOutcome | string;
|
|
361
|
+
signalCode?: string;
|
|
362
|
+
signal_code?: string;
|
|
363
|
+
intentId?: string;
|
|
364
|
+
intent_id?: string;
|
|
365
|
+
providerEventId?: string;
|
|
366
|
+
provider_event_id?: string;
|
|
367
|
+
summary: string;
|
|
368
|
+
};
|
|
369
|
+
export type SignalFraudReviewEventResponse = {
|
|
370
|
+
schema_version: number;
|
|
371
|
+
tenant_id: string;
|
|
372
|
+
operator_did: string;
|
|
373
|
+
score_model_version: string;
|
|
374
|
+
requested_event_type: string;
|
|
375
|
+
recorded_event_type: string;
|
|
376
|
+
review_outcome?: string;
|
|
377
|
+
signal_code?: string;
|
|
378
|
+
intent_id?: string;
|
|
379
|
+
provider_event_id?: string;
|
|
380
|
+
accepted: boolean;
|
|
381
|
+
next_eligible_at?: string;
|
|
382
|
+
[key: string]: unknown;
|
|
383
|
+
};
|
|
384
|
+
export type ListFraudReviewQueueOptions = {
|
|
385
|
+
state?: SignalReviewState | string;
|
|
386
|
+
severity?: SignalFraudSeverity | string;
|
|
387
|
+
limit?: number;
|
|
388
|
+
scoreVersion?: string;
|
|
389
|
+
};
|
|
390
|
+
export type GetFraudMetricsOptions = {
|
|
391
|
+
window?: SignalFraudMetricsWindow | string;
|
|
392
|
+
scoreVersion?: string;
|
|
393
|
+
};
|
|
202
394
|
export type A2AAgentCard = {
|
|
203
395
|
name: string;
|
|
204
396
|
description: string;
|
|
@@ -616,6 +808,10 @@ type GatewaySignalClientOptions = {
|
|
|
616
808
|
staticGatewayBearerToken: string;
|
|
617
809
|
maxRetries?: number;
|
|
618
810
|
};
|
|
811
|
+
type GatewayFraudClientOptions = {
|
|
812
|
+
staticGatewayBearerToken: string;
|
|
813
|
+
maxRetries?: number;
|
|
814
|
+
};
|
|
619
815
|
/**
|
|
620
816
|
* Tenant-bound reader for gateway Signal routes.
|
|
621
817
|
*/
|
|
@@ -634,6 +830,34 @@ export declare class GatewaySignalClient {
|
|
|
634
830
|
getOperatorExplanation(operatorDid: string, scoreVersion?: string): Promise<Record<string, unknown> | null>;
|
|
635
831
|
getOperatorReviewStatus(operatorDid: string, scoreVersion?: string): Promise<Record<string, unknown> | null>;
|
|
636
832
|
}
|
|
833
|
+
/**
|
|
834
|
+
* Tenant-bound client for gateway fraud review and metrics routes.
|
|
835
|
+
*/
|
|
836
|
+
export declare class GatewayFraudClient {
|
|
837
|
+
private readonly base;
|
|
838
|
+
readonly tenantId: string;
|
|
839
|
+
private readonly bearerToken;
|
|
840
|
+
private readonly maxRetries;
|
|
841
|
+
constructor(gatewayBaseUrl: string, tenantId: string, options: GatewayFraudClientOptions);
|
|
842
|
+
private fetchGetWithRetries;
|
|
843
|
+
private fetchPostJSON;
|
|
844
|
+
private fetchPutJSON;
|
|
845
|
+
private assertTenant;
|
|
846
|
+
private assertOperator;
|
|
847
|
+
private query;
|
|
848
|
+
private normalizedSeverity;
|
|
849
|
+
private normalizedWindow;
|
|
850
|
+
private normalizedReleaseGateMode;
|
|
851
|
+
private normalizedReviewEventType;
|
|
852
|
+
private normalizedReviewOutcome;
|
|
853
|
+
private optionalReviewContext;
|
|
854
|
+
getFraudAssessment(operatorDid: string, scoreVersion?: string): Promise<SignalFraudAssessmentResponse | null>;
|
|
855
|
+
listFraudReviewQueue(options?: ListFraudReviewQueueOptions): Promise<SignalFraudReviewQueueResponse>;
|
|
856
|
+
getFraudMetrics(options?: GetFraudMetricsOptions): Promise<SignalFraudMetricsResponse>;
|
|
857
|
+
getFraudReleaseGateConfig(scoreVersion?: string): Promise<SignalFraudReleaseGateConfigResponse>;
|
|
858
|
+
setFraudReleaseGateMode(mode: SignalFraudReleaseGateMode | string): Promise<SignalFraudReleaseGateConfigResponse>;
|
|
859
|
+
recordFraudReviewEvent(operatorDid: string, event: SignalFraudReviewEventInput, scoreVersion?: string): Promise<SignalFraudReviewEventResponse>;
|
|
860
|
+
}
|
|
637
861
|
type GatewayA2AClientOptions = {
|
|
638
862
|
staticGatewayBearerToken?: string;
|
|
639
863
|
maxRetries?: number;
|
|
@@ -701,6 +925,7 @@ export type ServiceAccountSignalSessionInit = {
|
|
|
701
925
|
principalPath?: string;
|
|
702
926
|
maxRetries?: number;
|
|
703
927
|
};
|
|
928
|
+
export type ServiceAccountFraudSessionInit = ServiceAccountSignalSessionInit;
|
|
704
929
|
/**
|
|
705
930
|
* Read-only tenant-bound Signal session for one service-account API key.
|
|
706
931
|
*/
|
|
@@ -710,6 +935,15 @@ export declare class ServiceAccountSignalSession {
|
|
|
710
935
|
static open(init: ServiceAccountSignalSessionInit): Promise<ServiceAccountSignalSession>;
|
|
711
936
|
aclose(): Promise<void>;
|
|
712
937
|
}
|
|
938
|
+
/**
|
|
939
|
+
* Tenant-bound fraud review and metrics session for one service-account API key.
|
|
940
|
+
*/
|
|
941
|
+
export declare class ServiceAccountFraudSession {
|
|
942
|
+
readonly fraud: GatewayFraudClient;
|
|
943
|
+
private constructor();
|
|
944
|
+
static open(init: ServiceAccountFraudSessionInit): Promise<ServiceAccountFraudSession>;
|
|
945
|
+
aclose(): Promise<void>;
|
|
946
|
+
}
|
|
713
947
|
/**
|
|
714
948
|
* Parameters for {@link PaybondIntents.create} (tenant is taken from the bound Harbor client).
|
|
715
949
|
* `settlementRail`, when set, requests one allowed rail; Harbor still resolves the destination
|
|
@@ -754,6 +988,7 @@ export declare class PaybondIntents {
|
|
|
754
988
|
export declare class Paybond {
|
|
755
989
|
readonly harbor: HarborClient;
|
|
756
990
|
readonly signal: GatewaySignalClient;
|
|
991
|
+
readonly fraud: GatewayFraudClient;
|
|
757
992
|
readonly a2a: GatewayA2AClient;
|
|
758
993
|
readonly protocol: GatewayProtocolClient;
|
|
759
994
|
readonly intents: PaybondIntents;
|
package/dist/index.js
CHANGED
|
@@ -659,6 +659,16 @@ export class HarborClient {
|
|
|
659
659
|
}
|
|
660
660
|
const DEFAULT_PRINCIPAL_PATH = "/v1/auth/principal";
|
|
661
661
|
const SETTLEMENT_RAIL_VALUES = new Set(["stripe_connect", "x402_usdc_base"]);
|
|
662
|
+
const FRAUD_REVIEW_EVENT_TYPES = new Set([
|
|
663
|
+
"review_open_requested",
|
|
664
|
+
"appeal_requested",
|
|
665
|
+
"replay_requested",
|
|
666
|
+
"review_outcome_recorded",
|
|
667
|
+
"confirmed_risk",
|
|
668
|
+
"false_positive",
|
|
669
|
+
"needs_more_evidence",
|
|
670
|
+
]);
|
|
671
|
+
const FRAUD_REVIEW_OUTCOMES = new Set(["confirmed_risk", "false_positive", "needs_more_evidence"]);
|
|
662
672
|
function assertJSONObject(value) {
|
|
663
673
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
664
674
|
throw new Error("expected JSON object");
|
|
@@ -884,6 +894,286 @@ export class GatewaySignalClient {
|
|
|
884
894
|
return body;
|
|
885
895
|
}
|
|
886
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Tenant-bound client for gateway fraud review and metrics routes.
|
|
899
|
+
*/
|
|
900
|
+
export class GatewayFraudClient {
|
|
901
|
+
base;
|
|
902
|
+
tenantId;
|
|
903
|
+
bearerToken;
|
|
904
|
+
maxRetries;
|
|
905
|
+
constructor(gatewayBaseUrl, tenantId, options) {
|
|
906
|
+
this.base = normalizeBase(gatewayBaseUrl) + "/";
|
|
907
|
+
this.tenantId = tenantId.trim();
|
|
908
|
+
this.bearerToken = options.staticGatewayBearerToken.trim();
|
|
909
|
+
this.maxRetries = Math.max(1, options.maxRetries ?? 3);
|
|
910
|
+
}
|
|
911
|
+
async fetchGetWithRetries(url) {
|
|
912
|
+
let lastErr;
|
|
913
|
+
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
|
|
914
|
+
let res;
|
|
915
|
+
try {
|
|
916
|
+
res = await fetch(url, {
|
|
917
|
+
method: "GET",
|
|
918
|
+
headers: {
|
|
919
|
+
accept: "application/json",
|
|
920
|
+
authorization: `Bearer ${this.bearerToken}`,
|
|
921
|
+
},
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
catch (e) {
|
|
925
|
+
lastErr = e;
|
|
926
|
+
if (attempt + 1 >= this.maxRetries)
|
|
927
|
+
throw e;
|
|
928
|
+
await new Promise((r) => setTimeout(r, backoffMs(attempt)));
|
|
929
|
+
continue;
|
|
930
|
+
}
|
|
931
|
+
if ([429, 500, 502, 503, 504].includes(res.status)) {
|
|
932
|
+
if (attempt + 1 >= this.maxRetries) {
|
|
933
|
+
return res;
|
|
934
|
+
}
|
|
935
|
+
const raSec = parseRetryAfterSeconds(res.headers.get("retry-after"));
|
|
936
|
+
const delayMs = raSec != null ? raSec * 1000 : backoffMs(attempt);
|
|
937
|
+
await new Promise((r) => setTimeout(r, delayMs));
|
|
938
|
+
continue;
|
|
939
|
+
}
|
|
940
|
+
return res;
|
|
941
|
+
}
|
|
942
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
943
|
+
}
|
|
944
|
+
async fetchPostJSON(url, payload) {
|
|
945
|
+
return fetch(url, {
|
|
946
|
+
method: "POST",
|
|
947
|
+
headers: {
|
|
948
|
+
accept: "application/json",
|
|
949
|
+
authorization: `Bearer ${this.bearerToken}`,
|
|
950
|
+
"content-type": "application/json",
|
|
951
|
+
},
|
|
952
|
+
body: JSON.stringify(payload),
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
async fetchPutJSON(url, payload) {
|
|
956
|
+
return fetch(url, {
|
|
957
|
+
method: "PUT",
|
|
958
|
+
headers: {
|
|
959
|
+
accept: "application/json",
|
|
960
|
+
authorization: `Bearer ${this.bearerToken}`,
|
|
961
|
+
"content-type": "application/json",
|
|
962
|
+
},
|
|
963
|
+
body: JSON.stringify(payload),
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
assertTenant(body, url) {
|
|
967
|
+
const tid = String(body.tenant_id ?? "");
|
|
968
|
+
if (tid !== this.tenantId) {
|
|
969
|
+
throw new Error(`fraud tenant mismatch: client=${this.tenantId} gateway=${tid} url=${url}`);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
assertOperator(body, operatorDid, label) {
|
|
973
|
+
const echoedOperator = String(body.operator_did ?? "");
|
|
974
|
+
if (echoedOperator !== operatorDid) {
|
|
975
|
+
throw new Error(`fraud ${label} operator mismatch: requested=${operatorDid} gateway=${echoedOperator}`);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
query(params) {
|
|
979
|
+
const qs = new URLSearchParams();
|
|
980
|
+
for (const [key, value] of Object.entries(params)) {
|
|
981
|
+
if (typeof value === "number") {
|
|
982
|
+
qs.set(key, String(value));
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
if (typeof value === "string" && value.trim()) {
|
|
986
|
+
qs.set(key, value.trim());
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
const raw = qs.toString();
|
|
990
|
+
return raw ? `?${raw}` : "";
|
|
991
|
+
}
|
|
992
|
+
normalizedSeverity(severity) {
|
|
993
|
+
const normalized = severity?.trim();
|
|
994
|
+
if (!normalized) {
|
|
995
|
+
return undefined;
|
|
996
|
+
}
|
|
997
|
+
if (!["elevated", "high", "critical"].includes(normalized)) {
|
|
998
|
+
throw new Error("fraud severity must be one of elevated, high, or critical");
|
|
999
|
+
}
|
|
1000
|
+
return normalized;
|
|
1001
|
+
}
|
|
1002
|
+
normalizedWindow(window) {
|
|
1003
|
+
const normalized = window?.trim();
|
|
1004
|
+
if (!normalized) {
|
|
1005
|
+
return undefined;
|
|
1006
|
+
}
|
|
1007
|
+
if (!["24h", "7d", "30d"].includes(normalized)) {
|
|
1008
|
+
throw new Error("fraud metrics window must be one of 24h, 7d, or 30d");
|
|
1009
|
+
}
|
|
1010
|
+
return normalized;
|
|
1011
|
+
}
|
|
1012
|
+
normalizedReleaseGateMode(mode) {
|
|
1013
|
+
const normalized = mode.trim();
|
|
1014
|
+
if (!["review_only", "critical_hold"].includes(normalized)) {
|
|
1015
|
+
throw new Error("fraud release gate mode must be one of review_only or critical_hold");
|
|
1016
|
+
}
|
|
1017
|
+
return normalized;
|
|
1018
|
+
}
|
|
1019
|
+
normalizedReviewEventType(eventType) {
|
|
1020
|
+
const normalized = eventType.trim();
|
|
1021
|
+
if (!FRAUD_REVIEW_EVENT_TYPES.has(normalized)) {
|
|
1022
|
+
throw new Error("fraud review eventType must be one of review_open_requested, appeal_requested, replay_requested, review_outcome_recorded, confirmed_risk, false_positive, or needs_more_evidence");
|
|
1023
|
+
}
|
|
1024
|
+
return normalized;
|
|
1025
|
+
}
|
|
1026
|
+
normalizedReviewOutcome(outcome) {
|
|
1027
|
+
const normalized = outcome.trim();
|
|
1028
|
+
if (!FRAUD_REVIEW_OUTCOMES.has(normalized)) {
|
|
1029
|
+
throw new Error("fraud review outcome must be one of confirmed_risk, false_positive, or needs_more_evidence");
|
|
1030
|
+
}
|
|
1031
|
+
return normalized;
|
|
1032
|
+
}
|
|
1033
|
+
optionalReviewContext(value) {
|
|
1034
|
+
const normalized = value?.trim();
|
|
1035
|
+
return normalized || undefined;
|
|
1036
|
+
}
|
|
1037
|
+
async getFraudAssessment(operatorDid, scoreVersion) {
|
|
1038
|
+
const enc = encodeURIComponent(operatorDid);
|
|
1039
|
+
const url = `${this.base}signal/v1/operators/${enc}/review-status${this.query({
|
|
1040
|
+
score_version: scoreVersion,
|
|
1041
|
+
})}`;
|
|
1042
|
+
const res = await this.fetchGetWithRetries(url);
|
|
1043
|
+
const text = await res.text();
|
|
1044
|
+
if (res.status === 404) {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
if (!res.ok) {
|
|
1048
|
+
throw new SignalHttpError(`Fraud assessment HTTP ${res.status}: ${text}`, {
|
|
1049
|
+
statusCode: res.status,
|
|
1050
|
+
url,
|
|
1051
|
+
bodyText: text,
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1055
|
+
this.assertTenant(body, url);
|
|
1056
|
+
this.assertOperator(body, operatorDid, "assessment");
|
|
1057
|
+
return body;
|
|
1058
|
+
}
|
|
1059
|
+
async listFraudReviewQueue(options = {}) {
|
|
1060
|
+
let rawLimit;
|
|
1061
|
+
if (options.limit !== undefined) {
|
|
1062
|
+
if (!Number.isFinite(options.limit)) {
|
|
1063
|
+
throw new Error("fraud review queue limit must be a finite number");
|
|
1064
|
+
}
|
|
1065
|
+
rawLimit = Math.max(1, Math.min(Math.floor(options.limit), 500));
|
|
1066
|
+
}
|
|
1067
|
+
const url = `${this.base}signal/v1/review-queue${this.query({
|
|
1068
|
+
state: options.state,
|
|
1069
|
+
fraud_severity: this.normalizedSeverity(options.severity),
|
|
1070
|
+
limit: rawLimit,
|
|
1071
|
+
score_version: options.scoreVersion,
|
|
1072
|
+
})}`;
|
|
1073
|
+
const res = await this.fetchGetWithRetries(url);
|
|
1074
|
+
const text = await res.text();
|
|
1075
|
+
if (!res.ok) {
|
|
1076
|
+
throw new SignalHttpError(`Fraud review queue HTTP ${res.status}: ${text}`, {
|
|
1077
|
+
statusCode: res.status,
|
|
1078
|
+
url,
|
|
1079
|
+
bodyText: text,
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1083
|
+
this.assertTenant(body, url);
|
|
1084
|
+
return body;
|
|
1085
|
+
}
|
|
1086
|
+
async getFraudMetrics(options = {}) {
|
|
1087
|
+
const url = `${this.base}signal/v1/fraud/metrics${this.query({
|
|
1088
|
+
window: this.normalizedWindow(options.window),
|
|
1089
|
+
score_version: options.scoreVersion,
|
|
1090
|
+
})}`;
|
|
1091
|
+
const res = await this.fetchGetWithRetries(url);
|
|
1092
|
+
const text = await res.text();
|
|
1093
|
+
if (!res.ok) {
|
|
1094
|
+
throw new SignalHttpError(`Fraud metrics HTTP ${res.status}: ${text}`, {
|
|
1095
|
+
statusCode: res.status,
|
|
1096
|
+
url,
|
|
1097
|
+
bodyText: text,
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1101
|
+
this.assertTenant(body, url);
|
|
1102
|
+
return body;
|
|
1103
|
+
}
|
|
1104
|
+
async getFraudReleaseGateConfig(scoreVersion) {
|
|
1105
|
+
const url = `${this.base}signal/v1/fraud/release-gate${this.query({
|
|
1106
|
+
score_version: scoreVersion,
|
|
1107
|
+
})}`;
|
|
1108
|
+
const res = await this.fetchGetWithRetries(url);
|
|
1109
|
+
const text = await res.text();
|
|
1110
|
+
if (!res.ok) {
|
|
1111
|
+
throw new SignalHttpError(`Fraud release gate HTTP ${res.status}: ${text}`, {
|
|
1112
|
+
statusCode: res.status,
|
|
1113
|
+
url,
|
|
1114
|
+
bodyText: text,
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1118
|
+
this.assertTenant(body, url);
|
|
1119
|
+
return body;
|
|
1120
|
+
}
|
|
1121
|
+
async setFraudReleaseGateMode(mode) {
|
|
1122
|
+
const normalized = this.normalizedReleaseGateMode(mode);
|
|
1123
|
+
const url = `${this.base}signal/v1/fraud/release-gate`;
|
|
1124
|
+
const res = await this.fetchPutJSON(url, { mode: normalized });
|
|
1125
|
+
const text = await res.text();
|
|
1126
|
+
if (!res.ok) {
|
|
1127
|
+
throw new SignalHttpError(`Fraud release gate update HTTP ${res.status}: ${text}`, {
|
|
1128
|
+
statusCode: res.status,
|
|
1129
|
+
url,
|
|
1130
|
+
bodyText: text,
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1134
|
+
this.assertTenant(body, url);
|
|
1135
|
+
return body;
|
|
1136
|
+
}
|
|
1137
|
+
async recordFraudReviewEvent(operatorDid, event, scoreVersion) {
|
|
1138
|
+
let eventType = this.normalizedReviewEventType(event.eventType);
|
|
1139
|
+
let reviewOutcome = event.reviewOutcome ?? event.review_outcome;
|
|
1140
|
+
if (FRAUD_REVIEW_OUTCOMES.has(eventType)) {
|
|
1141
|
+
reviewOutcome = eventType;
|
|
1142
|
+
eventType = "review_outcome_recorded";
|
|
1143
|
+
}
|
|
1144
|
+
const normalizedOutcome = reviewOutcome === undefined ? undefined : this.normalizedReviewOutcome(reviewOutcome);
|
|
1145
|
+
if (eventType === "review_outcome_recorded" && normalizedOutcome === undefined) {
|
|
1146
|
+
throw new Error("fraud review outcome must be one of confirmed_risk, false_positive, or needs_more_evidence");
|
|
1147
|
+
}
|
|
1148
|
+
const signalCode = this.optionalReviewContext(event.signalCode ?? event.signal_code);
|
|
1149
|
+
const intentId = this.optionalReviewContext(event.intentId ?? event.intent_id);
|
|
1150
|
+
const providerEventId = this.optionalReviewContext(event.providerEventId ?? event.provider_event_id);
|
|
1151
|
+
const enc = encodeURIComponent(operatorDid);
|
|
1152
|
+
const url = `${this.base}signal/v1/operators/${enc}/review-events${this.query({
|
|
1153
|
+
score_version: scoreVersion,
|
|
1154
|
+
})}`;
|
|
1155
|
+
const res = await this.fetchPostJSON(url, {
|
|
1156
|
+
event_type: eventType,
|
|
1157
|
+
...(normalizedOutcome ? { review_outcome: normalizedOutcome } : {}),
|
|
1158
|
+
...(signalCode ? { signal_code: signalCode } : {}),
|
|
1159
|
+
...(intentId ? { intent_id: intentId } : {}),
|
|
1160
|
+
...(providerEventId ? { provider_event_id: providerEventId } : {}),
|
|
1161
|
+
summary: event.summary,
|
|
1162
|
+
});
|
|
1163
|
+
const text = await res.text();
|
|
1164
|
+
if (!res.ok && res.status !== 429) {
|
|
1165
|
+
throw new SignalHttpError(`Fraud review event HTTP ${res.status}: ${text}`, {
|
|
1166
|
+
statusCode: res.status,
|
|
1167
|
+
url,
|
|
1168
|
+
bodyText: text,
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
const body = assertJSONObject(JSON.parse(text));
|
|
1172
|
+
this.assertTenant(body, url);
|
|
1173
|
+
this.assertOperator(body, operatorDid, "review event");
|
|
1174
|
+
return body;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
887
1177
|
/**
|
|
888
1178
|
* Public or optionally authenticated reader for the gateway's A2A discovery surface.
|
|
889
1179
|
*/
|
|
@@ -1218,6 +1508,25 @@ export class ServiceAccountSignalSession {
|
|
|
1218
1508
|
await Promise.resolve();
|
|
1219
1509
|
}
|
|
1220
1510
|
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Tenant-bound fraud review and metrics session for one service-account API key.
|
|
1513
|
+
*/
|
|
1514
|
+
export class ServiceAccountFraudSession {
|
|
1515
|
+
fraud;
|
|
1516
|
+
constructor(fraud) {
|
|
1517
|
+
this.fraud = fraud;
|
|
1518
|
+
}
|
|
1519
|
+
static async open(init) {
|
|
1520
|
+
const tenantId = await resolveGatewayTenantId(init.gatewayBaseUrl, init.apiKey, init.principalPath ?? DEFAULT_PRINCIPAL_PATH, Math.max(1, init.maxRetries ?? 3));
|
|
1521
|
+
return new ServiceAccountFraudSession(new GatewayFraudClient(init.gatewayBaseUrl, tenantId, {
|
|
1522
|
+
staticGatewayBearerToken: init.apiKey,
|
|
1523
|
+
maxRetries: init.maxRetries ?? 3,
|
|
1524
|
+
}));
|
|
1525
|
+
}
|
|
1526
|
+
async aclose() {
|
|
1527
|
+
await Promise.resolve();
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1221
1530
|
/**
|
|
1222
1531
|
* Ergonomic intent helpers: principal-signed intent create, x402 funding, and payee-signed evidence.
|
|
1223
1532
|
*/
|
|
@@ -1267,14 +1576,16 @@ export class PaybondIntents {
|
|
|
1267
1576
|
export class Paybond {
|
|
1268
1577
|
harbor;
|
|
1269
1578
|
signal;
|
|
1579
|
+
fraud;
|
|
1270
1580
|
a2a;
|
|
1271
1581
|
protocol;
|
|
1272
1582
|
intents;
|
|
1273
1583
|
session;
|
|
1274
|
-
constructor(session, signal, a2a, protocol) {
|
|
1584
|
+
constructor(session, signal, fraud, a2a, protocol) {
|
|
1275
1585
|
this.session = session;
|
|
1276
1586
|
this.harbor = session.harbor;
|
|
1277
1587
|
this.signal = signal;
|
|
1588
|
+
this.fraud = fraud;
|
|
1278
1589
|
this.a2a = a2a;
|
|
1279
1590
|
this.protocol = protocol;
|
|
1280
1591
|
this.intents = new PaybondIntents(session.harbor);
|
|
@@ -1286,6 +1597,10 @@ export class Paybond {
|
|
|
1286
1597
|
staticGatewayBearerToken: init.apiKey,
|
|
1287
1598
|
maxRetries: init.maxRetries ?? 3,
|
|
1288
1599
|
});
|
|
1600
|
+
const fraud = new GatewayFraudClient(init.gatewayBaseUrl, session.harbor.tenantId, {
|
|
1601
|
+
staticGatewayBearerToken: init.apiKey,
|
|
1602
|
+
maxRetries: init.maxRetries ?? 3,
|
|
1603
|
+
});
|
|
1289
1604
|
const a2a = new GatewayA2AClient(init.gatewayBaseUrl, {
|
|
1290
1605
|
staticGatewayBearerToken: init.apiKey,
|
|
1291
1606
|
maxRetries: init.maxRetries ?? 3,
|
|
@@ -1294,7 +1609,7 @@ export class Paybond {
|
|
|
1294
1609
|
staticGatewayBearerToken: init.apiKey,
|
|
1295
1610
|
maxRetries: init.maxRetries ?? 3,
|
|
1296
1611
|
});
|
|
1297
|
-
return new Paybond(session, signal, a2a, protocol);
|
|
1612
|
+
return new Paybond(session, signal, fraud, a2a, protocol);
|
|
1298
1613
|
}
|
|
1299
1614
|
async rotateHarborToken() {
|
|
1300
1615
|
await this.session.rotateHarborToken();
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { GatewayAuthError, GatewaySignalClient, HarborHttpError, ServiceAccountHarborSession, SignalHttpError, } from "./index.js";
|
|
2
|
+
import { GatewayAuthError, GatewayFraudClient, GatewaySignalClient, HarborHttpError, ServiceAccountHarborSession, SignalHttpError, } from "./index.js";
|
|
3
3
|
const SERVER_NAME = "Paybond MCP";
|
|
4
|
-
const SERVER_VERSION = "0.
|
|
4
|
+
const SERVER_VERSION = "0.5.0";
|
|
5
5
|
const MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
6
6
|
const DEFAULT_HARBOR_ACCESS_PATH = "/v1/auth/harbor-access";
|
|
7
7
|
const DEFAULT_PRINCIPAL_PATH = "/v1/auth/principal";
|
|
@@ -114,6 +114,7 @@ class PaybondMCPRuntime {
|
|
|
114
114
|
gateway;
|
|
115
115
|
principalValue = null;
|
|
116
116
|
signalValue = null;
|
|
117
|
+
fraudValue = null;
|
|
117
118
|
harborValue = null;
|
|
118
119
|
constructor(settings) {
|
|
119
120
|
this.settings = {
|
|
@@ -150,6 +151,13 @@ class PaybondMCPRuntime {
|
|
|
150
151
|
}))();
|
|
151
152
|
return this.signalValue;
|
|
152
153
|
}
|
|
154
|
+
async fraud() {
|
|
155
|
+
this.fraudValue ??= (async () => new GatewayFraudClient(this.settings.gatewayBaseUrl, await this.tenantId(), {
|
|
156
|
+
staticGatewayBearerToken: this.settings.apiKey,
|
|
157
|
+
maxRetries: this.settings.maxRetries,
|
|
158
|
+
}))();
|
|
159
|
+
return this.fraudValue;
|
|
160
|
+
}
|
|
153
161
|
async harbor() {
|
|
154
162
|
if (!this.settings.harborBaseUrl) {
|
|
155
163
|
throw new Error("PAYBOND_HARBOR_URL is required for direct Harbor mutation tools");
|
|
@@ -529,6 +537,27 @@ export class PaybondMCPServer {
|
|
|
529
537
|
}),
|
|
530
538
|
call: async (args) => (await this.runtime.signal()).getSignedPortfolioArtifact(optionalString(args.score_version)),
|
|
531
539
|
},
|
|
540
|
+
{
|
|
541
|
+
name: "paybond_get_fraud_assessment",
|
|
542
|
+
description: "Fetch the read-only fraud assessment for one tenant-scoped operator DID.",
|
|
543
|
+
inputSchema: objectSchema({
|
|
544
|
+
operator_did: { type: "string" },
|
|
545
|
+
score_version: { type: "string" },
|
|
546
|
+
}, ["operator_did"]),
|
|
547
|
+
call: async (args) => (await this.runtime.fraud()).getFraudAssessment(stringArg(args.operator_did, "operator_did"), optionalString(args.score_version)),
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
name: "paybond_get_fraud_metrics",
|
|
551
|
+
description: "Fetch tenant-scoped read-only fraud backtesting and monitoring metrics for a supported active window.",
|
|
552
|
+
inputSchema: objectSchema({
|
|
553
|
+
window: { type: "string", enum: ["24h", "7d", "30d"] },
|
|
554
|
+
score_version: { type: "string" },
|
|
555
|
+
}),
|
|
556
|
+
call: async (args) => (await this.runtime.fraud()).getFraudMetrics({
|
|
557
|
+
window: optionalString(args.window),
|
|
558
|
+
scoreVersion: optionalString(args.score_version),
|
|
559
|
+
}),
|
|
560
|
+
},
|
|
532
561
|
{
|
|
533
562
|
name: "paybond_get_a2a_agent_card",
|
|
534
563
|
description: "Fetch the published Paybond A2A discovery card for protocol-trust delegation.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paybond/kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Paybond Kit for TypeScript: tenant-bound Harbor sessions, capability verification, and signed intent/evidence flows.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -38,11 +38,20 @@
|
|
|
38
38
|
"keywords": [
|
|
39
39
|
"paybond",
|
|
40
40
|
"harbor",
|
|
41
|
+
"kit",
|
|
41
42
|
"agents",
|
|
42
|
-
"
|
|
43
|
+
"agent-runtime",
|
|
44
|
+
"agent-payments",
|
|
43
45
|
"escrow",
|
|
46
|
+
"intent-escrow",
|
|
44
47
|
"capabilities",
|
|
45
|
-
"
|
|
48
|
+
"capability-verification",
|
|
49
|
+
"tenant-bound",
|
|
50
|
+
"x402",
|
|
51
|
+
"usdc",
|
|
52
|
+
"mcp",
|
|
53
|
+
"reputation",
|
|
54
|
+
"typescript"
|
|
46
55
|
],
|
|
47
56
|
"publishConfig": {
|
|
48
57
|
"access": "public",
|