@belticlabs/agent-risk-sdk 0.1.1 → 0.3.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/dist/adapter-BEpzr2R3.d.ts +29 -0
- package/dist/ai/index.d.ts +5 -5
- package/dist/ai/index.js +48 -36
- package/dist/chunk-4MG6VNAU.js +276 -0
- package/dist/chunk-FAQ442YH.js +24 -0
- package/dist/{chunk-U5Z5Z2BQ.js → chunk-LM4NIYE5.js} +26 -20
- package/dist/chunk-NJVO2WIV.js +17 -0
- package/dist/{chunk-W2OY7QXV.js → chunk-OKC6VMFH.js} +15 -26
- package/dist/{chunk-SFGM7KOG.js → chunk-X3W2Z5GC.js} +3 -0
- package/dist/index.d.ts +19 -9
- package/dist/index.js +354 -161
- package/dist/mcp/index.d.ts +3 -5
- package/dist/mcp/index.js +42 -34
- package/dist/middleware-9gI0ou2i.d.ts +15 -0
- package/dist/protocol/index.d.ts +2 -3
- package/dist/seller/anti-fraud-gateway.d.ts +11 -4
- package/dist/seller/anti-fraud-gateway.js +13 -14
- package/dist/session-DsBWEP8d.d.ts +485 -0
- package/dist/{index-Bjs3BPPU.d.ts → verdict-6vCyoAHE.d.ts} +25 -1
- package/dist/x402/express.d.ts +4 -6
- package/dist/x402/express.js +8 -7
- package/dist/x402/hono.d.ts +4 -6
- package/dist/x402/hono.js +8 -7
- package/dist/x402/index.d.ts +80 -19
- package/dist/x402/index.js +109 -35
- package/package.json +1 -1
- package/dist/chunk-5TWO73OD.js +0 -35
- package/dist/chunk-VM7MK43J.js +0 -13
- package/dist/client-NxpD_384.d.ts +0 -64
- package/dist/middleware-D-ejQIoE.d.ts +0 -40
- package/dist/session-B2mfurae.d.ts +0 -196
- package/dist/verdict-BAahb5po.d.ts +0 -26
package/dist/x402/index.d.ts
CHANGED
|
@@ -1,55 +1,116 @@
|
|
|
1
|
-
export { A as AttachOptions, b as AttachedX402, C as CorrelationContext,
|
|
2
|
-
import { S as
|
|
3
|
-
import { P as PaymentMomentPayload, J as JsonObject } from '../
|
|
4
|
-
import { PaymentPayload, PaymentRequired, PaymentRequirements } from '@x402/core/types';
|
|
1
|
+
export { A as AttachOptions, b as AttachedX402, C as CorrelationContext, a as attachX402 } from '../adapter-BEpzr2R3.js';
|
|
2
|
+
import { S as SessionSource } from '../session-DsBWEP8d.js';
|
|
3
|
+
import { v as DeclaredIntent, P as PaymentMomentPayload, J as JsonObject, a as PaymentSummary } from '../verdict-6vCyoAHE.js';
|
|
5
4
|
import '@x402/core/server';
|
|
6
|
-
import '../client-NxpD_384.js';
|
|
7
|
-
import '../verdict-BAahb5po.js';
|
|
8
5
|
import 'zod';
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* Session binding on the x402 rail (Fraud SDK RFC › Protocol Adapter — x402:
|
|
12
9
|
* "`PAYMENT-SIGNATURE` extension `beltic.sessionId`"). Where exactly it
|
|
13
10
|
* lives is GAP-30; that it is outside the wallet-signed payload is GAP-56.
|
|
11
|
+
* A presentation the buyer had evaluated first also carries the
|
|
12
|
+
* `decisionId` the platform answered with, next to the session (GAP-80).
|
|
14
13
|
*/
|
|
15
14
|
declare const SESSION_EXTENSION = "beltic.sessionId";
|
|
16
15
|
declare const SESSION_HEADER = "Beltic-Session-Id";
|
|
16
|
+
declare const DECISION_EXTENSION = "beltic.decisionId";
|
|
17
|
+
declare const DECISION_HEADER = "Beltic-Decision-Id";
|
|
17
18
|
declare function sessionIdOf(extensions: Readonly<Record<string, unknown>> | undefined): string | null;
|
|
19
|
+
declare function decisionIdOf(extensions: Readonly<Record<string, unknown>> | undefined): string | null;
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The paying fetch, observed. Takes a session or the run that owns one;
|
|
23
|
+
* without either (the evidence stream is not configured, or the platform
|
|
24
|
+
* refused to open one) the inner fetch is returned as is — or runs as is
|
|
25
|
+
* per request when the run has no session yet — so a host wires it
|
|
26
|
+
* unconditionally.
|
|
27
|
+
*/
|
|
28
|
+
declare function belticFetch(source: SessionSource, inner?: typeof globalThis.fetch): typeof globalThis.fetch;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The declared intent for an x402 mandate (Fraud SDK RFC › Session ›
|
|
32
|
+
* `intent.declared`). The cap must be in the currency the rail's moments
|
|
33
|
+
* carry — `<network>/<asset>`, atomic units (GAP-49) — or the platform's
|
|
34
|
+
* spend detectors compare two currencies and never meet; this is the one
|
|
35
|
+
* place a buyer spells that. Everything else is the protocol's own shape.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
interface X402IntentInput {
|
|
39
|
+
mandate: string;
|
|
40
|
+
network: string;
|
|
41
|
+
asset: string;
|
|
42
|
+
/** Atomic units of `asset`, as x402 carries amounts — a decimal string or a bigint, never a float. */
|
|
43
|
+
maxAmount: string | bigint;
|
|
44
|
+
validUntil: string | Date;
|
|
45
|
+
merchantAllowlist?: string[] | undefined;
|
|
46
|
+
}
|
|
47
|
+
declare function x402Intent(input: X402IntentInput): DeclaredIntent;
|
|
20
48
|
|
|
21
49
|
/**
|
|
22
50
|
* x402 artifacts → protocol moments (Fraud SDK RFC › Protocol Adapter —
|
|
23
51
|
* x402). The moment is normalized (payee, amount, payer) so both sides of
|
|
24
52
|
* a purchase compare; the artifact travels whole in `raw`. For x402 the
|
|
25
53
|
* currency is `<network>/<asset>` (GAP-49) and the value is the atomic
|
|
26
|
-
* amount as the protocol carries it
|
|
54
|
+
* amount as the protocol carries it — `x402Summary` gives a buyer the same
|
|
55
|
+
* normalization for the payment it is about to evaluate, so what it asks
|
|
56
|
+
* about and what the wrapper records are one and the same.
|
|
27
57
|
*/
|
|
28
58
|
|
|
29
|
-
type Readonlyish<T> = {
|
|
30
|
-
readonly [K in keyof T]: Readonlyish<T[K]>;
|
|
31
|
-
} | T;
|
|
32
59
|
declare function x402Currency(network: string, asset: string): string;
|
|
33
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* The minimum an `accepts` entry needs to become a moment; unknown parts
|
|
62
|
+
* are named, never dropped. v1 spells the amount `maxAmountRequired`.
|
|
63
|
+
*/
|
|
34
64
|
interface AcceptsLike {
|
|
35
65
|
payTo?: string | undefined;
|
|
36
66
|
amount?: string | undefined;
|
|
67
|
+
maxAmountRequired?: string | undefined;
|
|
37
68
|
network?: string | undefined;
|
|
38
69
|
asset?: string | undefined;
|
|
39
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* A 402 challenge and a presented payment of either generation, as far as
|
|
73
|
+
* a moment needs them. `@x402/core`'s `PaymentRequired` and
|
|
74
|
+
* `PaymentPayload` satisfy these structurally, so the seller adapter
|
|
75
|
+
* passes its typed values through and the buyer needs no `@x402/*` types.
|
|
76
|
+
*/
|
|
77
|
+
interface PaymentRequiredLike {
|
|
78
|
+
x402Version?: number | undefined;
|
|
79
|
+
accepts?: readonly AcceptsLike[] | undefined;
|
|
80
|
+
}
|
|
81
|
+
interface PaymentPayloadLike {
|
|
82
|
+
x402Version?: number | undefined;
|
|
83
|
+
accepted?: AcceptsLike | undefined;
|
|
84
|
+
/** v1 names the network here, beside the payload, and nowhere else. */
|
|
85
|
+
network?: string | undefined;
|
|
86
|
+
payload?: Readonly<Record<string, unknown>> | undefined;
|
|
87
|
+
extensions?: Readonly<Record<string, unknown>> | undefined;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The one normalization of an x402 `accepts` entry: the payment in the
|
|
91
|
+
* shape `evaluate` takes, with the payer as `payerOf` would read it. Every
|
|
92
|
+
* moment below is this plus its artifact and `raw`.
|
|
93
|
+
*/
|
|
94
|
+
declare function x402Summary(accepts: AcceptsLike | undefined, opts?: {
|
|
95
|
+
payer?: string | undefined;
|
|
96
|
+
}): PaymentSummary;
|
|
40
97
|
/** The payer is scheme-specific; the common EVM shapes are read, anything else stays in `raw`. */
|
|
41
|
-
declare function payerOf(payload:
|
|
98
|
+
declare function payerOf(payload: PaymentPayloadLike): string | undefined;
|
|
42
99
|
declare const x402Moments: {
|
|
43
|
-
/** The 402 challenge as the buyer saw it. */
|
|
44
|
-
required(required:
|
|
100
|
+
/** The 402 challenge as the buyer saw it, v2 header or v1 body. */
|
|
101
|
+
required(required: PaymentRequiredLike): PaymentMomentPayload;
|
|
45
102
|
/** The requirements the seller's resource server resolved for a request. */
|
|
46
|
-
requirements(req:
|
|
103
|
+
requirements(req: AcceptsLike): PaymentMomentPayload;
|
|
47
104
|
/** A route's static `accepts` config, before any payment header exists. */
|
|
48
105
|
route(route: unknown, raw: JsonObject): PaymentMomentPayload;
|
|
49
106
|
/** An in-band ask (MRTR `input_required` or a `_meta` envelope) carrying an x402-style `accepts`. */
|
|
50
107
|
ask(first: AcceptsLike, raw: JsonObject): PaymentMomentPayload;
|
|
51
|
-
/**
|
|
52
|
-
|
|
108
|
+
/**
|
|
109
|
+
* The signed payment the buyer presented. A v2 payload carries the
|
|
110
|
+
* requirement it accepted; a v1 payload does not, so the caller passes
|
|
111
|
+
* the `accepts` entry it answered.
|
|
112
|
+
*/
|
|
113
|
+
payload(payload: PaymentPayloadLike, accepts?: AcceptsLike | undefined): PaymentMomentPayload;
|
|
53
114
|
};
|
|
54
115
|
|
|
55
|
-
export { type AcceptsLike, SESSION_EXTENSION, SESSION_HEADER, belticFetch, payerOf, sessionIdOf, x402Currency, x402Moments };
|
|
116
|
+
export { type AcceptsLike, DECISION_EXTENSION, DECISION_HEADER, type PaymentPayloadLike, type PaymentRequiredLike, SESSION_EXTENSION, SESSION_HEADER, type X402IntentInput, belticFetch, decisionIdOf, payerOf, sessionIdOf, x402Currency, x402Intent, x402Moments, x402Summary };
|
package/dist/x402/index.js
CHANGED
|
@@ -1,67 +1,141 @@
|
|
|
1
1
|
import {
|
|
2
|
-
attachX402
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
attachX402
|
|
3
|
+
} from "../chunk-OKC6VMFH.js";
|
|
4
|
+
import {
|
|
5
|
+
Session,
|
|
6
|
+
Sessions
|
|
7
|
+
} from "../chunk-4MG6VNAU.js";
|
|
5
8
|
import {
|
|
9
|
+
DECISION_EXTENSION,
|
|
10
|
+
DECISION_HEADER,
|
|
6
11
|
SESSION_EXTENSION,
|
|
7
12
|
SESSION_HEADER,
|
|
13
|
+
decisionIdOf,
|
|
8
14
|
sessionIdOf
|
|
9
|
-
} from "../chunk-
|
|
10
|
-
import "../chunk-
|
|
15
|
+
} from "../chunk-FAQ442YH.js";
|
|
16
|
+
import "../chunk-X3W2Z5GC.js";
|
|
17
|
+
import "../chunk-46QN2KEZ.js";
|
|
11
18
|
import {
|
|
12
19
|
payerOf,
|
|
13
20
|
x402Currency,
|
|
14
|
-
x402Moments
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
x402Moments,
|
|
22
|
+
x402Summary
|
|
23
|
+
} from "../chunk-LM4NIYE5.js";
|
|
17
24
|
import "../chunk-FQDHFTVR.js";
|
|
18
|
-
import "../chunk-46QN2KEZ.js";
|
|
19
25
|
|
|
20
26
|
// src/x402/fetch.ts
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
var BASE64 = /^[A-Za-z0-9+/]*={0,2}$/;
|
|
28
|
+
var CHALLENGE_MEMORY = 32;
|
|
29
|
+
function belticFetch(source, inner = globalThis.fetch) {
|
|
30
|
+
if (!source) return inner;
|
|
31
|
+
const run = source instanceof Session ? null : source;
|
|
32
|
+
const challenges = /* @__PURE__ */ new Map();
|
|
27
33
|
return async (input, init) => {
|
|
34
|
+
const session = await Sessions.resolve(source);
|
|
35
|
+
if (!session) return inner(input, init);
|
|
36
|
+
const url = urlOf(input);
|
|
28
37
|
const headers = new Headers(
|
|
29
38
|
init?.headers ?? (input instanceof Request ? input.headers : void 0)
|
|
30
39
|
);
|
|
31
40
|
headers.set(SESSION_HEADER, session.id);
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
const signature = headers.get("PAYMENT-SIGNATURE");
|
|
42
|
+
const presented = signature ?? headers.get("X-PAYMENT");
|
|
43
|
+
const payload = presented ? decodeHeader(presented) : null;
|
|
44
|
+
if (payload) {
|
|
45
|
+
const accepts = payload.accepted ?? answeredAccepts(challenges.get(url), payload);
|
|
46
|
+
const decision = run?.decisionFor(x402Moments.payload(payload, accepts));
|
|
47
|
+
const decisionId = decision && !decision.absent ? decision.decisionId : null;
|
|
48
|
+
const bound = signature ? {
|
|
49
|
+
...payload,
|
|
50
|
+
extensions: {
|
|
51
|
+
...payload.extensions,
|
|
52
|
+
[SESSION_EXTENSION]: session.id,
|
|
53
|
+
...decisionId ? { [DECISION_EXTENSION]: decisionId } : {}
|
|
54
|
+
}
|
|
55
|
+
} : payload;
|
|
56
|
+
if (signature) headers.set("PAYMENT-SIGNATURE", encodeHeader(bound));
|
|
57
|
+
else if (decisionId) headers.set(DECISION_HEADER, decisionId);
|
|
58
|
+
await session.emit("payment.presented", x402Moments.payload(bound, accepts));
|
|
59
|
+
await session.flush();
|
|
42
60
|
}
|
|
43
61
|
const res = await inner(input, { ...init, headers });
|
|
44
|
-
|
|
62
|
+
if (res.status !== 402) return res;
|
|
63
|
+
const required = await challengeOf(res);
|
|
45
64
|
if (required) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
x402Moments.required(decodePaymentRequiredHeader(required))
|
|
50
|
-
);
|
|
51
|
-
} catch {
|
|
52
|
-
}
|
|
65
|
+
challenges.set(url, required);
|
|
66
|
+
if (challenges.size > CHALLENGE_MEMORY) challenges.delete(challenges.keys().next().value);
|
|
67
|
+
await session.emit("payment.requested", x402Moments.required(required));
|
|
53
68
|
}
|
|
54
69
|
return res;
|
|
55
70
|
};
|
|
56
71
|
}
|
|
72
|
+
function decodeHeader(value) {
|
|
73
|
+
if (!BASE64.test(value)) return null;
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(Buffer.from(value, "base64").toString("utf8"));
|
|
76
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function encodeHeader(value) {
|
|
82
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64");
|
|
83
|
+
}
|
|
84
|
+
function urlOf(input) {
|
|
85
|
+
return typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
86
|
+
}
|
|
87
|
+
async function challengeOf(res) {
|
|
88
|
+
const header = res.headers.get("PAYMENT-REQUIRED");
|
|
89
|
+
if (header) return decodeHeader(header);
|
|
90
|
+
if (!/json/i.test(res.headers.get("content-type") ?? "")) return null;
|
|
91
|
+
try {
|
|
92
|
+
const body = await res.clone().json();
|
|
93
|
+
return Array.isArray(body?.accepts) ? body : null;
|
|
94
|
+
} catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function answeredAccepts(required, payload) {
|
|
99
|
+
const auth = payload.payload?.authorization;
|
|
100
|
+
const payTo = typeof auth?.to === "string" ? auth.to : void 0;
|
|
101
|
+
const amount = typeof auth?.value === "string" ? auth.value : void 0;
|
|
102
|
+
const options = required?.accepts ?? [];
|
|
103
|
+
const answered = options.find(
|
|
104
|
+
(a) => a.payTo?.toLowerCase() === payTo?.toLowerCase() && (a.amount ?? a.maxAmountRequired) === amount
|
|
105
|
+
) ?? options[0];
|
|
106
|
+
if (answered) return answered;
|
|
107
|
+
if (!payTo && !amount) return void 0;
|
|
108
|
+
return {
|
|
109
|
+
...payTo ? { payTo } : {},
|
|
110
|
+
...amount ? { amount } : {},
|
|
111
|
+
...payload.network ? { network: payload.network } : {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/x402/intent.ts
|
|
116
|
+
function x402Intent(input) {
|
|
117
|
+
return {
|
|
118
|
+
mandate: input.mandate,
|
|
119
|
+
maxAmount: {
|
|
120
|
+
value: input.maxAmount.toString(),
|
|
121
|
+
currency: x402Currency(input.network, input.asset)
|
|
122
|
+
},
|
|
123
|
+
validUntil: new Date(input.validUntil).toISOString(),
|
|
124
|
+
...input.merchantAllowlist ? { merchantAllowlist: input.merchantAllowlist } : {}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
57
127
|
export {
|
|
128
|
+
DECISION_EXTENSION,
|
|
129
|
+
DECISION_HEADER,
|
|
58
130
|
SESSION_EXTENSION,
|
|
59
131
|
SESSION_HEADER,
|
|
60
132
|
attachX402,
|
|
61
133
|
belticFetch,
|
|
62
|
-
|
|
134
|
+
decisionIdOf,
|
|
63
135
|
payerOf,
|
|
64
136
|
sessionIdOf,
|
|
65
137
|
x402Currency,
|
|
66
|
-
|
|
138
|
+
x402Intent,
|
|
139
|
+
x402Moments,
|
|
140
|
+
x402Summary
|
|
67
141
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@belticlabs/agent-risk-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The Beltic Agent Risk SDK — one client, two halves: instrument the buyer agent (AI SDK, x402 fetch, MCP client) and guard the seller boundary (x402, MCP server, evaluate).",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
package/dist/chunk-5TWO73OD.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// src/core/record.ts
|
|
2
|
-
function errorOf(err) {
|
|
3
|
-
const e = err;
|
|
4
|
-
return { name: String(e?.name ?? "Error"), message: String(e?.message ?? err) };
|
|
5
|
-
}
|
|
6
|
-
async function recordCall(session, kind, callId, start, run, end = () => ({})) {
|
|
7
|
-
const started = Date.now();
|
|
8
|
-
await session.emit(`${kind}.start`, { callId, ...start });
|
|
9
|
-
try {
|
|
10
|
-
const result = await run();
|
|
11
|
-
await session.emit(
|
|
12
|
-
`${kind}.end`,
|
|
13
|
-
{
|
|
14
|
-
callId,
|
|
15
|
-
...await end(result),
|
|
16
|
-
durationMs: Date.now() - started
|
|
17
|
-
}
|
|
18
|
-
);
|
|
19
|
-
return result;
|
|
20
|
-
} catch (err) {
|
|
21
|
-
await session.emit(
|
|
22
|
-
`${kind}.end`,
|
|
23
|
-
{
|
|
24
|
-
callId,
|
|
25
|
-
error: errorOf(err),
|
|
26
|
-
durationMs: Date.now() - started
|
|
27
|
-
}
|
|
28
|
-
);
|
|
29
|
-
throw err;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
recordCall
|
|
35
|
-
};
|
package/dist/chunk-VM7MK43J.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// src/x402/binding.ts
|
|
2
|
-
var SESSION_EXTENSION = "beltic.sessionId";
|
|
3
|
-
var SESSION_HEADER = "Beltic-Session-Id";
|
|
4
|
-
function sessionIdOf(extensions) {
|
|
5
|
-
const v = extensions?.[SESSION_EXTENSION];
|
|
6
|
-
return typeof v === "string" && v.length > 0 ? v : null;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
SESSION_EXTENSION,
|
|
11
|
-
SESSION_HEADER,
|
|
12
|
-
sessionIdOf
|
|
13
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { a as PaymentSummary, B as EvaluateOutput } from './index-Bjs3BPPU.js';
|
|
2
|
-
import { O as OnReview } from './verdict-BAahb5po.js';
|
|
3
|
-
import { a as ApiClient, T as Transport, d as Sessions, A as AgentIdentity, b as ApiClientOptions, g as TransportOptions, R as RedactFn } from './session-B2mfurae.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Correlation without binding (Fraud SDK RFC › Protocol Adapter — x402:
|
|
7
|
-
* "binding travels on the call that initiates the purchase, not
|
|
8
|
-
* necessarily on the payment artifact"). The merchant binds a key it will
|
|
9
|
-
* see again (a checkout session id, a challenge nonce) to the buyer's
|
|
10
|
-
* session; the adapter resolves it when the settlement arrives (GAP-31).
|
|
11
|
-
*/
|
|
12
|
-
interface CorrelationStore {
|
|
13
|
-
bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
|
|
14
|
-
resolve(key: string): Promise<string | null>;
|
|
15
|
-
}
|
|
16
|
-
declare class MemoryCorrelationStore implements CorrelationStore {
|
|
17
|
-
private readonly defaultTtlMs;
|
|
18
|
-
private readonly entries;
|
|
19
|
-
constructor(defaultTtlMs?: number);
|
|
20
|
-
bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
|
|
21
|
-
resolve(key: string): Promise<string | null>;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* One SDK, two halves (Fraud SDK RFC › Summary). `Beltic` is the single
|
|
26
|
-
* client: sessions and evidence for both halves, `evaluate` for the seller
|
|
27
|
-
* half. Protocol integrations are plain functions behind subpath exports,
|
|
28
|
-
* each pulling exactly one optional peer:
|
|
29
|
-
*
|
|
30
|
-
* @belticlabs/agent-risk-sdk/ai → middleware(session), wrapTools(session, …)
|
|
31
|
-
* @belticlabs/agent-risk-sdk/x402 → belticFetch(session), attachX402(beltic, …)
|
|
32
|
-
* @belticlabs/agent-risk-sdk/hono → belticPaymentMiddleware(beltic, …) (and /express)
|
|
33
|
-
* @belticlabs/agent-risk-sdk/mcp → wrapClient(session, …), wrapServer(beltic, …)
|
|
34
|
-
*
|
|
35
|
-
* Neither half decides risk locally: verdicts are platform-side.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
declare const SDK_VERSION = "0.1.1";
|
|
39
|
-
interface BelticOptions extends Omit<ApiClientOptions, 'userAgent'> {
|
|
40
|
-
/** Buyer half. Without it, `sessions.start` is unavailable; the seller half works. */
|
|
41
|
-
identity?: AgentIdentity | undefined;
|
|
42
|
-
transport?: Partial<TransportOptions> | undefined;
|
|
43
|
-
/** What a synchronous seller hook does with REVIEW (GAP-52). */
|
|
44
|
-
onReview?: OnReview | undefined;
|
|
45
|
-
correlation?: CorrelationStore | undefined;
|
|
46
|
-
redact?: RedactFn | undefined;
|
|
47
|
-
now?: (() => Date) | undefined;
|
|
48
|
-
}
|
|
49
|
-
declare class Beltic {
|
|
50
|
-
readonly api: ApiClient;
|
|
51
|
-
readonly transport: Transport;
|
|
52
|
-
readonly sessions: Sessions;
|
|
53
|
-
readonly identity: AgentIdentity | undefined;
|
|
54
|
-
readonly correlation: CorrelationStore;
|
|
55
|
-
readonly onReview: OnReview;
|
|
56
|
-
constructor(opts: BelticOptions);
|
|
57
|
-
/** Read-your-writes: the platform must hold the evidence before it judges it (GAP-16). */
|
|
58
|
-
evaluate(sessionId: string, payment: PaymentSummary): Promise<EvaluateOutput>;
|
|
59
|
-
flush(): Promise<void>;
|
|
60
|
-
shutdown(): Promise<void>;
|
|
61
|
-
}
|
|
62
|
-
declare function createBeltic(opts: BelticOptions): Beltic;
|
|
63
|
-
|
|
64
|
-
export { Beltic as B, type CorrelationStore as C, MemoryCorrelationStore as M, SDK_VERSION as S, type BelticOptions as a, createBeltic as c };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { x402ResourceServer, x402HTTPResourceServer, PaywallConfig, RoutesConfig } from '@x402/core/server';
|
|
2
|
-
import { B as Beltic } from './client-NxpD_384.js';
|
|
3
|
-
import { D as Decision } from './index-Bjs3BPPU.js';
|
|
4
|
-
import { c as SessionBorn, S as Session } from './session-B2mfurae.js';
|
|
5
|
-
|
|
6
|
-
interface CorrelationContext {
|
|
7
|
-
path: string;
|
|
8
|
-
method: string;
|
|
9
|
-
header: (name: string) => string | undefined;
|
|
10
|
-
}
|
|
11
|
-
interface AttachOptions {
|
|
12
|
-
/** A key the merchant will see again at verify time, for delegated flows (GAP-31). */
|
|
13
|
-
correlate?: ((ctx: CorrelationContext) => string | null) | undefined;
|
|
14
|
-
/** Called with every decision; the default logs nothing. */
|
|
15
|
-
onDecision?: ((d: {
|
|
16
|
-
sessionId: string;
|
|
17
|
-
decision: Decision;
|
|
18
|
-
reasonCodes: string[];
|
|
19
|
-
born: SessionBorn;
|
|
20
|
-
}) => void) | undefined;
|
|
21
|
-
}
|
|
22
|
-
interface AttachedX402 {
|
|
23
|
-
/** Sessions resolved at verify time, keyed by payment digest — for tests and settle hooks. */
|
|
24
|
-
readonly inFlight: ReadonlyMap<string, Session>;
|
|
25
|
-
}
|
|
26
|
-
declare function attachX402(beltic: Beltic, server: x402ResourceServer, http?: x402HTTPResourceServer, opts?: AttachOptions): AttachedX402;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The seller half as one middleware: the framework's `@x402/*` payment
|
|
30
|
-
* middleware over an `x402HTTPResourceServer` with the Beltic hooks
|
|
31
|
-
* attached. `@belticlabs/agent-risk-sdk/hono` and `@belticlabs/agent-risk-sdk/express` differ only in
|
|
32
|
-
* which `paymentMiddlewareFromHTTPServer` they hand in.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
type GuardedMiddlewareOptions = AttachOptions & {
|
|
36
|
-
paywall?: PaywallConfig | undefined;
|
|
37
|
-
};
|
|
38
|
-
declare function guardedPaymentMiddleware<M>(fromHTTPServer: (http: x402HTTPResourceServer, paywall?: PaywallConfig) => M, beltic: Beltic, routes: RoutesConfig, server: x402ResourceServer, opts?: GuardedMiddlewareOptions): M;
|
|
39
|
-
|
|
40
|
-
export { type AttachOptions as A, type CorrelationContext as C, type GuardedMiddlewareOptions as G, attachX402 as a, type AttachedX402 as b, guardedPaymentMiddleware as g };
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { L as EvidenceAck, G as EventResult, R as EvidenceEvent, V as EvidenceSource, aC as WireEvidenceKind, J as JsonObject, C as ChainHead, aa as PayloadByKind, am as SessionClosePayload, v as DeclaredIntent } from './index-Bjs3BPPU.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The edge signs event digests (Fraud SDK RFC › Modules › Identity Module);
|
|
5
|
-
* the platform signs its own PLATFORM chain and epoch anchors. Both are the
|
|
6
|
-
* same operation over different keys, so one interface.
|
|
7
|
-
*/
|
|
8
|
-
interface Signer {
|
|
9
|
-
/** Raw 32-byte Ed25519 public key. */
|
|
10
|
-
readonly publicKey: Uint8Array;
|
|
11
|
-
/** Stable identifier for logs and key rotation; `did:key` for agents. */
|
|
12
|
-
readonly keyId: string;
|
|
13
|
-
sign(message: Uint8Array): Promise<Uint8Array>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface ApiClientOptions {
|
|
17
|
-
baseUrl: string;
|
|
18
|
-
apiKey: string;
|
|
19
|
-
fetch?: typeof globalThis.fetch;
|
|
20
|
-
timeoutMs?: number;
|
|
21
|
-
userAgent?: string;
|
|
22
|
-
}
|
|
23
|
-
declare class BelticApiError extends Error {
|
|
24
|
-
readonly status: number;
|
|
25
|
-
readonly code: string;
|
|
26
|
-
readonly details?: unknown | undefined;
|
|
27
|
-
readonly requestId?: string | undefined;
|
|
28
|
-
constructor(status: number, code: string, message: string, details?: unknown | undefined, requestId?: string | undefined);
|
|
29
|
-
/** 5xx and network failures are retried by the transport; 4xx are not. */
|
|
30
|
-
get retryable(): boolean;
|
|
31
|
-
}
|
|
32
|
-
declare class ApiClient {
|
|
33
|
-
private readonly baseUrl;
|
|
34
|
-
private readonly fetchImpl;
|
|
35
|
-
private readonly timeoutMs;
|
|
36
|
-
private readonly headers;
|
|
37
|
-
constructor(opts: ApiClientOptions);
|
|
38
|
-
post<T>(path: string, body: unknown, headers?: Record<string, string>): Promise<T>;
|
|
39
|
-
get<T>(path: string, query?: Record<string, string | undefined>): Promise<T>;
|
|
40
|
-
private request;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface AgentIdentity {
|
|
44
|
-
did: string;
|
|
45
|
-
signer: Signer;
|
|
46
|
-
/** Opaque credential presented at session start (stored, not verified this phase). */
|
|
47
|
-
credential?: string;
|
|
48
|
-
}
|
|
49
|
-
declare function identityFromSeed(seed: Uint8Array, credential?: string): AgentIdentity;
|
|
50
|
-
declare function ephemeralIdentity(credential?: string): AgentIdentity;
|
|
51
|
-
/** A JSON keystore on disk: `{ "seed": "<64 hex>" }`, created 0600 when missing. */
|
|
52
|
-
declare function fileIdentity(path: string, credential?: string): AgentIdentity;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Transport (Fraud SDK RFC › Modules: "buffering, batching, chained delivery
|
|
56
|
-
* to the Collector"). Contract as assumed in GAP-18/38: one FIFO per
|
|
57
|
-
* chain; at most one batch in flight per chain, so order is preserved;
|
|
58
|
-
* exponential backoff on network / 5xx; a `fork` or `rejected` ack halts
|
|
59
|
-
* the chain and surfaces `ChainRejectedError` — an SDK must not silently
|
|
60
|
-
* keep chaining onto a head the platform never accepted.
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
interface TransportOptions {
|
|
64
|
-
maxBatch: number;
|
|
65
|
-
flushMs: number;
|
|
66
|
-
/** Total buffered events across chains; beyond this new events are dropped (GAP-38). */
|
|
67
|
-
maxBuffered: number;
|
|
68
|
-
backoff: {
|
|
69
|
-
baseMs: number;
|
|
70
|
-
maxMs: number;
|
|
71
|
-
maxAttempts: number;
|
|
72
|
-
};
|
|
73
|
-
onAck?: (ack: EvidenceAck) => void;
|
|
74
|
-
onError?: (err: Error) => void;
|
|
75
|
-
onChainHalted?: (err: ChainRejectedError) => void;
|
|
76
|
-
setTimeout?: typeof globalThis.setTimeout;
|
|
77
|
-
clearTimeout?: typeof globalThis.clearTimeout;
|
|
78
|
-
}
|
|
79
|
-
declare const DEFAULT_TRANSPORT: TransportOptions;
|
|
80
|
-
declare class ChainRejectedError extends Error {
|
|
81
|
-
readonly sessionId: string;
|
|
82
|
-
readonly source: string;
|
|
83
|
-
readonly result: EventResult;
|
|
84
|
-
constructor(sessionId: string, source: string, result: EventResult);
|
|
85
|
-
}
|
|
86
|
-
declare class TransportClosedError extends Error {
|
|
87
|
-
constructor();
|
|
88
|
-
}
|
|
89
|
-
declare class Transport {
|
|
90
|
-
private readonly api;
|
|
91
|
-
private readonly opts;
|
|
92
|
-
private readonly chains;
|
|
93
|
-
private buffered;
|
|
94
|
-
private timer;
|
|
95
|
-
private closed;
|
|
96
|
-
private inFlightCount;
|
|
97
|
-
private drainWaiters;
|
|
98
|
-
constructor(api: ApiClient, opts?: Partial<TransportOptions>);
|
|
99
|
-
get size(): number;
|
|
100
|
-
hasRoom(): boolean;
|
|
101
|
-
haltedError(sessionId: string, source: string): ChainRejectedError | null;
|
|
102
|
-
/** Callers check `hasRoom()` first and assign `seq` only then (GAP-38). */
|
|
103
|
-
enqueue(ev: EvidenceEvent): void;
|
|
104
|
-
/** Send everything pending and wait for every in-flight batch to settle (ack or halt). */
|
|
105
|
-
flush(): Promise<void>;
|
|
106
|
-
close(): Promise<void>;
|
|
107
|
-
private schedule;
|
|
108
|
-
private unschedule;
|
|
109
|
-
private drained;
|
|
110
|
-
private settleWaiters;
|
|
111
|
-
private flushChain;
|
|
112
|
-
private send;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* A risk session as the SDK sees it: one chain per (sessionId, source),
|
|
117
|
-
* built at the edge (Fraud SDK RFC › Wire contract). The buyer half opens
|
|
118
|
-
* AGENT_TRACE sessions and announces them with `session.open` (seq 0) and
|
|
119
|
-
* `intent.declared` (seq 1; GAP-23/60); the seller half attaches to a bound
|
|
120
|
-
* session or opens its own INTERNAL_NETWORK session (GAP-13).
|
|
121
|
-
*
|
|
122
|
-
* `seq` is handed out only when the transport has room for the event
|
|
123
|
-
* (GAP-38): a dropped event never leaves a hole — the next accepted event
|
|
124
|
-
* is preceded by a `transport.gap` that counts the drops. `redact` is off
|
|
125
|
-
* by default (GAP-33).
|
|
126
|
-
*/
|
|
127
|
-
|
|
128
|
-
type RedactFn = (kind: WireEvidenceKind, payload: JsonObject) => JsonObject;
|
|
129
|
-
/** Who created the session — the seller half treats a bound session as buyer-born. */
|
|
130
|
-
type SessionBorn = 'buyer' | 'seller';
|
|
131
|
-
interface SessionDeps {
|
|
132
|
-
transport: Transport;
|
|
133
|
-
signer?: Signer | undefined;
|
|
134
|
-
redact?: RedactFn | undefined;
|
|
135
|
-
now?: (() => Date) | undefined;
|
|
136
|
-
/** Called once the session closed, so the registry can forget it. */
|
|
137
|
-
onClosed?: ((session: Session) => void) | undefined;
|
|
138
|
-
}
|
|
139
|
-
declare class Session {
|
|
140
|
-
private readonly deps;
|
|
141
|
-
readonly id: string;
|
|
142
|
-
readonly source: EvidenceSource;
|
|
143
|
-
readonly expiresAt: string | null;
|
|
144
|
-
readonly born: SessionBorn;
|
|
145
|
-
private chain;
|
|
146
|
-
private building;
|
|
147
|
-
private dropped;
|
|
148
|
-
private droppedFirstTs;
|
|
149
|
-
private droppedLastTs;
|
|
150
|
-
private closed;
|
|
151
|
-
private readonly now;
|
|
152
|
-
constructor(deps: SessionDeps, id: string, source: EvidenceSource, expiresAt: string | null, born: SessionBorn);
|
|
153
|
-
get head(): ChainHead | null;
|
|
154
|
-
get droppedCount(): number;
|
|
155
|
-
/** Resolves once the event is sequenced and buffered — not once it is acknowledged. */
|
|
156
|
-
emit<K extends WireEvidenceKind>(kind: K, payload: PayloadByKind[K]): Promise<boolean>;
|
|
157
|
-
close(reason?: SessionClosePayload['reason'], extra?: JsonObject): Promise<void>;
|
|
158
|
-
/** Read-your-writes: the platform must hold the evidence before anyone judges it (GAP-16/66). */
|
|
159
|
-
flush(): Promise<void>;
|
|
160
|
-
/** Serialized: two concurrent emits get consecutive seqs, never the same one. */
|
|
161
|
-
private next;
|
|
162
|
-
}
|
|
163
|
-
interface StartSessionInput {
|
|
164
|
-
intent?: DeclaredIntent;
|
|
165
|
-
runtime?: {
|
|
166
|
-
framework?: string;
|
|
167
|
-
model?: string;
|
|
168
|
-
};
|
|
169
|
-
attestations?: JsonObject;
|
|
170
|
-
}
|
|
171
|
-
interface SessionsDeps {
|
|
172
|
-
api: ApiClient;
|
|
173
|
-
transport: Transport;
|
|
174
|
-
identity?: AgentIdentity | undefined;
|
|
175
|
-
redact?: RedactFn | undefined;
|
|
176
|
-
now?: (() => Date) | undefined;
|
|
177
|
-
sdkVersion: string;
|
|
178
|
-
}
|
|
179
|
-
declare class Sessions {
|
|
180
|
-
private readonly deps;
|
|
181
|
-
/**
|
|
182
|
-
* One session object per (session, source) per process: a chain's head
|
|
183
|
-
* lives in it, so two objects for the same chain would both start at
|
|
184
|
-
* seq 0 and fork it. Closed sessions are forgotten; a process restart
|
|
185
|
-
* mid-session still loses the head (GAP-67).
|
|
186
|
-
*/
|
|
187
|
-
private readonly attached;
|
|
188
|
-
constructor(deps: SessionsDeps);
|
|
189
|
-
/** Buyer half: create an AGENT_TRACE session bound to the agent identity, then announce it on the chain. */
|
|
190
|
-
start(input?: StartSessionInput): Promise<Session>;
|
|
191
|
-
/** Seller half: emit INTERNAL_NETWORK evidence into a session the buyer bound, or open a seller-born one. */
|
|
192
|
-
ensure(sessionId?: string | null): Promise<Session>;
|
|
193
|
-
private attach;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export { type AgentIdentity as A, BelticApiError as B, ChainRejectedError as C, DEFAULT_TRANSPORT as D, type RedactFn as R, Session as S, Transport as T, ApiClient as a, type ApiClientOptions as b, type SessionBorn as c, Sessions as d, type StartSessionInput as e, TransportClosedError as f, type TransportOptions as g, ephemeralIdentity as h, fileIdentity as i, identityFromSeed as j };
|