@belticlabs/agent-risk-sdk 0.2.0 → 0.4.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-CF-cUYSA.d.ts → adapter-CLy44CD2.d.ts} +4 -3
- package/dist/ai/index.d.ts +5 -5
- package/dist/ai/index.js +49 -39
- package/dist/{chunk-46QN2KEZ.js → chunk-4BUUPU3O.js} +0 -9
- package/dist/chunk-4MG6VNAU.js +276 -0
- package/dist/chunk-WY5ZX4BD.js +177 -0
- package/dist/{chunk-SFGM7KOG.js → chunk-X3W2Z5GC.js} +3 -0
- package/dist/index.d.ts +15 -6
- package/dist/index.js +329 -228
- package/dist/protocol/index.d.ts +2 -3
- package/dist/protocol/index.js +1 -5
- package/dist/session-gK51QVAM.d.ts +484 -0
- package/dist/{index-Bjs3BPPU.d.ts → verdict-CDAsxktI.d.ts} +25 -17
- package/dist/x402/hono.d.ts +16 -7
- package/dist/x402/hono.js +14 -8
- package/dist/x402/index.d.ts +22 -46
- package/dist/x402/index.js +33 -53
- package/package.json +2 -30
- package/dist/chunk-7G5EHNVW.js +0 -17
- package/dist/chunk-GSH5APZW.js +0 -39
- package/dist/chunk-LM4NIYE5.js +0 -92
- package/dist/chunk-SO6HPRJT.js +0 -82
- package/dist/chunk-U7HM37CB.js +0 -17
- package/dist/chunk-VM7MK43J.js +0 -13
- package/dist/client-C-mV_3A0.d.ts +0 -91
- package/dist/mcp/index.d.ts +0 -60
- package/dist/mcp/index.js +0 -130
- package/dist/middleware-BwAYpBTl.d.ts +0 -15
- package/dist/seller/anti-fraud-gateway.d.ts +0 -42
- package/dist/seller/anti-fraud-gateway.js +0 -38
- package/dist/session-5TClPLI4.d.ts +0 -250
- package/dist/verdict-BAahb5po.d.ts +0 -26
- package/dist/x402/express.d.ts +0 -15
- package/dist/x402/express.js +0 -27
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { a as PaymentSummary, P as PaymentMomentPayload, B as EvaluateOutput } from './index-Bjs3BPPU.js';
|
|
2
|
-
import { O as OnReview, V as Verdict } from './verdict-BAahb5po.js';
|
|
3
|
-
import { a as ApiClient, g as Transport, e as Sessions, A as AgentIdentity, b as ApiClientOptions, i as TransportOptions, R as RedactFn } from './session-5TClPLI4.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 whichever
|
|
27
|
-
* half is about to let a payment through. Protocol integrations are plain
|
|
28
|
-
* functions behind subpath exports, 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), x402Summary(…), 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
|
-
* Evidence is a side channel of the work it observes. With `failOpen`
|
|
38
|
-
* nothing the SDK does throws into that work: `Session.emit` reports and
|
|
39
|
-
* answers `false`, `sessions.open` answers `null`, `evaluate` answers
|
|
40
|
-
* `null` — never an invented verdict; the host decides what to do without
|
|
41
|
-
* one (GAP-70). `sessions.start` and `sessions.ensure` throw either way:
|
|
42
|
-
* they are the primitives the fail-open entries are built on.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
declare const SDK_VERSION = "0.2.0";
|
|
46
|
-
interface BelticOptions extends Omit<ApiClientOptions, 'userAgent'> {
|
|
47
|
-
/** Buyer half. Without it, `sessions.start` is unavailable; the seller half works. */
|
|
48
|
-
identity?: AgentIdentity | undefined;
|
|
49
|
-
transport?: Partial<TransportOptions> | undefined;
|
|
50
|
-
/** What a synchronous seller hook does with REVIEW (GAP-52). */
|
|
51
|
-
onReview?: OnReview | undefined;
|
|
52
|
-
correlation?: CorrelationStore | undefined;
|
|
53
|
-
redact?: RedactFn | undefined;
|
|
54
|
-
now?: (() => Date) | undefined;
|
|
55
|
-
/** Evidence never fails the work it observes; see the module note (GAP-70). */
|
|
56
|
-
failOpen?: boolean | undefined;
|
|
57
|
-
/** Where fail-open failures go (and transport delivery failures unless `transport` names its own). Default: `console.error`. */
|
|
58
|
-
onError?: ((err: Error) => void) | undefined;
|
|
59
|
-
/** Fail-open only: how long `sessions.open` answers null after the platform refused to open a session (GAP-71). */
|
|
60
|
-
openRetryMs?: number | undefined;
|
|
61
|
-
}
|
|
62
|
-
/** The platform's answer, with the verdict as a value the caller can ask `blocks(onReview)`. */
|
|
63
|
-
type Evaluation = EvaluateOutput & {
|
|
64
|
-
verdict: Verdict;
|
|
65
|
-
};
|
|
66
|
-
declare class Beltic {
|
|
67
|
-
readonly api: ApiClient;
|
|
68
|
-
readonly transport: Transport;
|
|
69
|
-
readonly sessions: Sessions;
|
|
70
|
-
readonly identity: AgentIdentity | undefined;
|
|
71
|
-
readonly correlation: CorrelationStore;
|
|
72
|
-
readonly onReview: OnReview;
|
|
73
|
-
readonly failOpen: boolean;
|
|
74
|
-
private readonly onError;
|
|
75
|
-
constructor(opts: BelticOptions);
|
|
76
|
-
/**
|
|
77
|
-
* The platform's verdict on a payment — the seller's before it verifies,
|
|
78
|
-
* the buyer's before it presents. Read-your-writes: the buffered evidence
|
|
79
|
-
* is flushed first so the platform judges what the caller already saw
|
|
80
|
-
* (GAP-16). A recorded moment is accepted as is: only its comparable core
|
|
81
|
-
* (payee, amount, payer) is sent. `null` only under `failOpen`, when the
|
|
82
|
-
* platform could not be asked.
|
|
83
|
-
*/
|
|
84
|
-
evaluate(sessionId: string, payment: PaymentSummary | PaymentMomentPayload): Promise<Evaluation | null>;
|
|
85
|
-
private decide;
|
|
86
|
-
flush(): Promise<void>;
|
|
87
|
-
shutdown(): Promise<void>;
|
|
88
|
-
}
|
|
89
|
-
declare function createBeltic(opts: BelticOptions): Beltic;
|
|
90
|
-
|
|
91
|
-
export { Beltic as B, type CorrelationStore as C, type Evaluation as E, MemoryCorrelationStore as M, SDK_VERSION as S, type BelticOptions as a, createBeltic as c };
|
package/dist/mcp/index.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { a as PaymentSummary, P as PaymentMomentPayload } from '../index-Bjs3BPPU.js';
|
|
2
|
-
import { B as Beltic } from '../client-C-mV_3A0.js';
|
|
3
|
-
import { S as Session } from '../session-5TClPLI4.js';
|
|
4
|
-
import 'zod';
|
|
5
|
-
import '../verdict-BAahb5po.js';
|
|
6
|
-
|
|
7
|
-
interface CallToolParams {
|
|
8
|
-
name: string;
|
|
9
|
-
arguments?: Record<string, unknown> | undefined;
|
|
10
|
-
_meta?: Record<string, unknown> | undefined;
|
|
11
|
-
}
|
|
12
|
-
/** Structural: `Client` from `@modelcontextprotocol/sdk/client` satisfies it. */
|
|
13
|
-
interface McpClientLike {
|
|
14
|
-
callTool(params: CallToolParams, ...rest: unknown[]): Promise<unknown>;
|
|
15
|
-
}
|
|
16
|
-
declare function wrapClient<C extends McpClientLike>(session: Session | null | undefined, client: C, opts?: {
|
|
17
|
-
server?: string;
|
|
18
|
-
}): C;
|
|
19
|
-
/**
|
|
20
|
-
* An in-band payment ask: any object in the result carrying an x402-style
|
|
21
|
-
* `accepts` array (MRTR `input_required`, or a `_meta` envelope). One
|
|
22
|
-
* moment, two artifacts — either becomes the same `payment.requested`.
|
|
23
|
-
*/
|
|
24
|
-
declare function findPaymentAsk(result: unknown): PaymentMomentPayload | null;
|
|
25
|
-
interface ServerCallExtra {
|
|
26
|
-
_meta?: Record<string, unknown> | undefined;
|
|
27
|
-
sessionId?: string | undefined;
|
|
28
|
-
}
|
|
29
|
-
interface WithBelticOptions<Args> {
|
|
30
|
-
toolName: string;
|
|
31
|
-
/** Return the payment this call moves, or null when the call is not value-moving. */
|
|
32
|
-
valueMoving?: (args: Args) => PaymentSummary | null;
|
|
33
|
-
gateway?: string;
|
|
34
|
-
}
|
|
35
|
-
type ToolHandler<Args, R> = (args: Args, extra: ServerCallExtra) => Promise<R> | R;
|
|
36
|
-
interface McpErrorResult {
|
|
37
|
-
isError: true;
|
|
38
|
-
content: Array<{
|
|
39
|
-
type: 'text';
|
|
40
|
-
text: string;
|
|
41
|
-
}>;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Wraps a tool handler on the seller side. Value-moving calls are evaluated
|
|
45
|
-
* synchronously (DENY ⇒ isError result); every decided call is recorded
|
|
46
|
-
* as `gateway.decision` in the buyer's session, or a seller-born one.
|
|
47
|
-
*/
|
|
48
|
-
declare function withBeltic<Args, R>(beltic: Beltic, handler: ToolHandler<Args, R>, opts: WithBelticOptions<Args>): ToolHandler<Args, R | McpErrorResult>;
|
|
49
|
-
/** Structural: `McpServer` from `@modelcontextprotocol/sdk/server/mcp` satisfies it. */
|
|
50
|
-
interface McpServerLike {
|
|
51
|
-
registerTool(name: string, config: unknown, cb: (...a: never[]) => unknown): unknown;
|
|
52
|
-
}
|
|
53
|
-
interface WrapServerOptions {
|
|
54
|
-
valueMoving?: (toolName: string, args: unknown) => PaymentSummary | null;
|
|
55
|
-
gateway?: string;
|
|
56
|
-
}
|
|
57
|
-
/** Patches `registerTool` so every tool goes through `withBeltic`; `valueMoving` decides per tool. */
|
|
58
|
-
declare function wrapServer<S extends McpServerLike>(beltic: Beltic, server: S, opts?: WrapServerOptions): S;
|
|
59
|
-
|
|
60
|
-
export { type CallToolParams, type McpClientLike, type McpErrorResult, type McpServerLike, type ServerCallExtra, type ToolHandler, type WithBelticOptions, type WrapServerOptions, findPaymentAsk, withBeltic, wrapClient, wrapServer };
|
package/dist/mcp/index.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
recordCall
|
|
3
|
-
} from "../chunk-GSH5APZW.js";
|
|
4
|
-
import {
|
|
5
|
-
SESSION_EXTENSION
|
|
6
|
-
} from "../chunk-VM7MK43J.js";
|
|
7
|
-
import {
|
|
8
|
-
uuidv7
|
|
9
|
-
} from "../chunk-SFGM7KOG.js";
|
|
10
|
-
import {
|
|
11
|
-
Verdict
|
|
12
|
-
} from "../chunk-46QN2KEZ.js";
|
|
13
|
-
import {
|
|
14
|
-
presentedFrom
|
|
15
|
-
} from "../chunk-7G5EHNVW.js";
|
|
16
|
-
import {
|
|
17
|
-
x402Moments
|
|
18
|
-
} from "../chunk-LM4NIYE5.js";
|
|
19
|
-
import {
|
|
20
|
-
toJson,
|
|
21
|
-
toJsonObject
|
|
22
|
-
} from "../chunk-FQDHFTVR.js";
|
|
23
|
-
|
|
24
|
-
// src/mcp/index.ts
|
|
25
|
-
function wrapClient(session, client, opts = {}) {
|
|
26
|
-
if (!session) return client;
|
|
27
|
-
const original = client.callTool.bind(client);
|
|
28
|
-
const callTool = (params, ...rest) => recordCall(
|
|
29
|
-
session,
|
|
30
|
-
"tool_call",
|
|
31
|
-
uuidv7(),
|
|
32
|
-
{
|
|
33
|
-
toolName: params.name,
|
|
34
|
-
input: toJson(params.arguments ?? {}),
|
|
35
|
-
transport: "mcp",
|
|
36
|
-
...opts.server ? { server: opts.server } : {}
|
|
37
|
-
},
|
|
38
|
-
async () => {
|
|
39
|
-
await session.flush();
|
|
40
|
-
return original(
|
|
41
|
-
{ ...params, _meta: { ...params._meta ?? {}, [SESSION_EXTENSION]: session.id } },
|
|
42
|
-
...rest
|
|
43
|
-
);
|
|
44
|
-
},
|
|
45
|
-
async (result) => {
|
|
46
|
-
const ask = findPaymentAsk(result);
|
|
47
|
-
if (ask) await session.emit("payment.requested", ask);
|
|
48
|
-
return { output: toJson(result) };
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
return new Proxy(client, {
|
|
52
|
-
get(target, prop, receiver) {
|
|
53
|
-
return prop === "callTool" ? callTool : Reflect.get(target, prop, receiver);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function findPaymentAsk(result) {
|
|
58
|
-
const seen = /* @__PURE__ */ new Set();
|
|
59
|
-
const walk = (v, depth) => {
|
|
60
|
-
if (!v || typeof v !== "object" || seen.has(v) || depth > 6) return null;
|
|
61
|
-
seen.add(v);
|
|
62
|
-
const o = v;
|
|
63
|
-
const first = Array.isArray(o.accepts) ? o.accepts[0] : void 0;
|
|
64
|
-
if (typeof first?.payTo === "string") {
|
|
65
|
-
return x402Moments.ask(first, toJsonObject(o));
|
|
66
|
-
}
|
|
67
|
-
for (const child of Array.isArray(o) ? o : Object.values(o)) {
|
|
68
|
-
const hit = walk(child, depth + 1);
|
|
69
|
-
if (hit) return hit;
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
};
|
|
73
|
-
return walk(result, 0);
|
|
74
|
-
}
|
|
75
|
-
function withBeltic(beltic, handler, opts) {
|
|
76
|
-
const gateway = opts.gateway ?? "sdk-mcp";
|
|
77
|
-
return async (args, extra) => {
|
|
78
|
-
const bound = extra?._meta?.[SESSION_EXTENSION];
|
|
79
|
-
const session = await beltic.sessions.ensure(typeof bound === "string" ? bound : null);
|
|
80
|
-
const payment = opts.valueMoving?.(args) ?? null;
|
|
81
|
-
let verdict = Verdict.ALLOW;
|
|
82
|
-
let reasonCodes = [];
|
|
83
|
-
if (payment) {
|
|
84
|
-
await session.emit(
|
|
85
|
-
"payment.presented",
|
|
86
|
-
presentedFrom(payment, { tool: opts.toolName, args: toJson(args) })
|
|
87
|
-
);
|
|
88
|
-
const out = await beltic.evaluate(session.id, payment);
|
|
89
|
-
if (out) {
|
|
90
|
-
verdict = out.verdict;
|
|
91
|
-
reasonCodes = out.reasonCodes;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
await session.emit("gateway.decision", {
|
|
95
|
-
gateway,
|
|
96
|
-
call: { tool: opts.toolName, args: toJson(args) },
|
|
97
|
-
decision: verdict.effective(beltic.onReview),
|
|
98
|
-
reasonCodes,
|
|
99
|
-
record: { valueMoving: payment !== null, bound: typeof bound === "string" }
|
|
100
|
-
});
|
|
101
|
-
if (verdict.blocks(beltic.onReview)) {
|
|
102
|
-
return {
|
|
103
|
-
isError: true,
|
|
104
|
-
content: [
|
|
105
|
-
{ type: "text", text: `Beltic ${verdict.value}: ${reasonCodes.join(",") || "denied"}` }
|
|
106
|
-
]
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
return handler(args, extra);
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
function wrapServer(beltic, server, opts = {}) {
|
|
113
|
-
const original = server.registerTool.bind(server);
|
|
114
|
-
server.registerTool = ((name, config, cb) => original(
|
|
115
|
-
name,
|
|
116
|
-
config,
|
|
117
|
-
withBeltic(beltic, cb, {
|
|
118
|
-
toolName: name,
|
|
119
|
-
...opts.gateway ? { gateway: opts.gateway } : {},
|
|
120
|
-
valueMoving: (args) => opts.valueMoving?.(name, args) ?? null
|
|
121
|
-
})
|
|
122
|
-
));
|
|
123
|
-
return server;
|
|
124
|
-
}
|
|
125
|
-
export {
|
|
126
|
-
findPaymentAsk,
|
|
127
|
-
withBeltic,
|
|
128
|
-
wrapClient,
|
|
129
|
-
wrapServer
|
|
130
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { PaywallConfig } from '@x402/core/server';
|
|
2
|
-
import { A as AttachOptions } from './adapter-CF-cUYSA.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The seller half as one middleware: the framework's `@x402/*` payment
|
|
6
|
-
* middleware over an `x402HTTPResourceServer` with the Beltic hooks
|
|
7
|
-
* attached. `@belticlabs/agent-risk-sdk/hono` and `@belticlabs/agent-risk-sdk/express` differ only in
|
|
8
|
-
* which `paymentMiddlewareFromHTTPServer` they hand in.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
type GuardedMiddlewareOptions = AttachOptions & {
|
|
12
|
-
paywall?: PaywallConfig | undefined;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export type { GuardedMiddlewareOptions as G };
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { B as Beltic } from '../client-C-mV_3A0.js';
|
|
2
|
-
import '../index-Bjs3BPPU.js';
|
|
3
|
-
import 'zod';
|
|
4
|
-
import '../verdict-BAahb5po.js';
|
|
5
|
-
import '../session-5TClPLI4.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Adapter for the anti-fraud port already in Beltic's `platform` monorepo
|
|
9
|
-
* (`x402-core/gateways/anti-fraud.gateway.interface.ts`), GAP-37. That
|
|
10
|
-
* port is binary and session-less; the mapping is lossy by construction:
|
|
11
|
-
* `REVIEW` becomes a deny unless `onReview` says otherwise, and reason
|
|
12
|
-
* codes travel joined in `reason`. The structural type is copied so this
|
|
13
|
-
* module needs no dependency on `platform`.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
interface PaymentRiskContext {
|
|
17
|
-
wallet: string;
|
|
18
|
-
resource: string;
|
|
19
|
-
amountAtomic: string;
|
|
20
|
-
asset: string;
|
|
21
|
-
network: string;
|
|
22
|
-
paymentIdentifier?: string;
|
|
23
|
-
/** Not in the platform port yet — pass it when you have it. */
|
|
24
|
-
sessionId?: string;
|
|
25
|
-
payTo?: string;
|
|
26
|
-
}
|
|
27
|
-
type RiskDecision = {
|
|
28
|
-
allow: true;
|
|
29
|
-
} | {
|
|
30
|
-
allow: false;
|
|
31
|
-
reason: string;
|
|
32
|
-
};
|
|
33
|
-
interface AntiFraudGateway {
|
|
34
|
-
assess(context: PaymentRiskContext): Promise<RiskDecision>;
|
|
35
|
-
}
|
|
36
|
-
declare class BelticAntiFraudGateway implements AntiFraudGateway {
|
|
37
|
-
private readonly beltic;
|
|
38
|
-
constructor(beltic: Beltic);
|
|
39
|
-
assess(ctx: PaymentRiskContext): Promise<RiskDecision>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export { type AntiFraudGateway, BelticAntiFraudGateway, type PaymentRiskContext, type RiskDecision };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
presentedFrom
|
|
3
|
-
} from "../chunk-7G5EHNVW.js";
|
|
4
|
-
import {
|
|
5
|
-
x402Summary
|
|
6
|
-
} from "../chunk-LM4NIYE5.js";
|
|
7
|
-
import "../chunk-FQDHFTVR.js";
|
|
8
|
-
|
|
9
|
-
// src/seller/anti-fraud-gateway.ts
|
|
10
|
-
var BelticAntiFraudGateway = class {
|
|
11
|
-
constructor(beltic) {
|
|
12
|
-
this.beltic = beltic;
|
|
13
|
-
}
|
|
14
|
-
async assess(ctx) {
|
|
15
|
-
const session = await this.beltic.sessions.ensure(ctx.sessionId ?? null);
|
|
16
|
-
const payment = x402Summary(
|
|
17
|
-
{
|
|
18
|
-
payTo: ctx.payTo ?? ctx.resource,
|
|
19
|
-
amount: ctx.amountAtomic,
|
|
20
|
-
network: ctx.network,
|
|
21
|
-
asset: ctx.asset
|
|
22
|
-
},
|
|
23
|
-
{ payer: ctx.wallet }
|
|
24
|
-
);
|
|
25
|
-
await session.emit(
|
|
26
|
-
"payment.presented",
|
|
27
|
-
presentedFrom(payment, {
|
|
28
|
-
resource: ctx.resource,
|
|
29
|
-
...ctx.paymentIdentifier ? { paymentIdentifier: ctx.paymentIdentifier } : {}
|
|
30
|
-
})
|
|
31
|
-
);
|
|
32
|
-
const out = await this.beltic.evaluate(session.id, payment);
|
|
33
|
-
return out?.verdict.blocks(this.beltic.onReview) ? { allow: false, reason: `${out.decision}:${out.reasonCodes.join(",")}` } : { allow: true };
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
export {
|
|
37
|
-
BelticAntiFraudGateway
|
|
38
|
-
};
|
|
@@ -1,250 +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, aw as ToolCallStartPayload, b as JsonValue, 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
|
-
* Evidence is a side channel of the agent's work: with `failOpen` an emit
|
|
128
|
-
* that cannot be chained (halted chain, closed transport) is reported and
|
|
129
|
-
* returns `false` instead of throwing into the model or tool call it
|
|
130
|
-
* observes (GAP-70).
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
type RedactFn = (kind: WireEvidenceKind, payload: JsonObject) => JsonObject;
|
|
134
|
-
/** Who created the session — the seller half treats a bound session as buyer-born. */
|
|
135
|
-
type SessionBorn = 'buyer' | 'seller';
|
|
136
|
-
interface SessionDeps {
|
|
137
|
-
transport: Transport;
|
|
138
|
-
signer?: Signer | undefined;
|
|
139
|
-
redact?: RedactFn | undefined;
|
|
140
|
-
now?: (() => Date) | undefined;
|
|
141
|
-
/** Called once the session closed, so the registry can forget it. */
|
|
142
|
-
onClosed?: ((session: Session) => void) | undefined;
|
|
143
|
-
/** Report instead of throw when an event cannot be chained (GAP-70). */
|
|
144
|
-
failOpen?: boolean | undefined;
|
|
145
|
-
onError?: ((err: Error) => void) | undefined;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* One tool call as a span: `tool_call.start` now, `tool_call.end` with the
|
|
149
|
-
* outcome and the elapsed time when the host reports it. For hosts that run
|
|
150
|
-
* their own tool loop and cannot hand the SDK an `execute` to wrap.
|
|
151
|
-
*/
|
|
152
|
-
interface ToolCallSpan {
|
|
153
|
-
readonly callId: string;
|
|
154
|
-
end(outcome?: {
|
|
155
|
-
output?: JsonValue;
|
|
156
|
-
}): Promise<boolean>;
|
|
157
|
-
fail(error: unknown, outcome?: {
|
|
158
|
-
output?: JsonValue;
|
|
159
|
-
}): Promise<boolean>;
|
|
160
|
-
}
|
|
161
|
-
declare class Session {
|
|
162
|
-
private readonly deps;
|
|
163
|
-
readonly id: string;
|
|
164
|
-
readonly source: EvidenceSource;
|
|
165
|
-
readonly expiresAt: string | null;
|
|
166
|
-
readonly born: SessionBorn;
|
|
167
|
-
private chain;
|
|
168
|
-
private building;
|
|
169
|
-
private dropped;
|
|
170
|
-
private droppedFirstTs;
|
|
171
|
-
private droppedLastTs;
|
|
172
|
-
private closed;
|
|
173
|
-
private readonly now;
|
|
174
|
-
constructor(deps: SessionDeps, id: string, source: EvidenceSource, expiresAt: string | null, born: SessionBorn);
|
|
175
|
-
get head(): ChainHead | null;
|
|
176
|
-
get droppedCount(): number;
|
|
177
|
-
/**
|
|
178
|
-
* Resolves once the event is sequenced and buffered — not once it is
|
|
179
|
-
* acknowledged. `false` when the event was dropped, or (fail-open) when
|
|
180
|
-
* the chain can no longer take it.
|
|
181
|
-
*/
|
|
182
|
-
emit<K extends WireEvidenceKind>(kind: K, payload: PayloadByKind[K]): Promise<boolean>;
|
|
183
|
-
/** The tool call whose `execute` the host runs itself; see `ToolCallSpan`. */
|
|
184
|
-
toolCall(call: ToolCallStartPayload): ToolCallSpan;
|
|
185
|
-
private chainEvent;
|
|
186
|
-
close(reason?: SessionClosePayload['reason'], extra?: JsonObject): Promise<void>;
|
|
187
|
-
/** Read-your-writes: the platform must hold the evidence before anyone judges it (GAP-16/66). */
|
|
188
|
-
flush(): Promise<void>;
|
|
189
|
-
/** Serialized: two concurrent emits get consecutive seqs, never the same one. */
|
|
190
|
-
private next;
|
|
191
|
-
}
|
|
192
|
-
interface StartSessionInput {
|
|
193
|
-
intent?: DeclaredIntent;
|
|
194
|
-
runtime?: {
|
|
195
|
-
framework?: string;
|
|
196
|
-
model?: string;
|
|
197
|
-
};
|
|
198
|
-
attestations?: JsonObject;
|
|
199
|
-
}
|
|
200
|
-
/** What `open` sends when it actually opens: a value, or a resolver run only then. */
|
|
201
|
-
type OpenSessionInput = StartSessionInput | (() => StartSessionInput | Promise<StartSessionInput>);
|
|
202
|
-
interface SessionsDeps {
|
|
203
|
-
api: ApiClient;
|
|
204
|
-
transport: Transport;
|
|
205
|
-
identity?: AgentIdentity | undefined;
|
|
206
|
-
redact?: RedactFn | undefined;
|
|
207
|
-
now?: (() => Date) | undefined;
|
|
208
|
-
sdkVersion: string;
|
|
209
|
-
failOpen?: boolean | undefined;
|
|
210
|
-
onError?: ((err: Error) => void) | undefined;
|
|
211
|
-
/** Fail-open only: after the platform refused to open a session, `open` resolves null for this long (GAP-71). */
|
|
212
|
-
openRetryMs?: number | undefined;
|
|
213
|
-
}
|
|
214
|
-
declare const DEFAULT_OPEN_RETRY_MS = 60000;
|
|
215
|
-
declare class Sessions {
|
|
216
|
-
private readonly deps;
|
|
217
|
-
/**
|
|
218
|
-
* One session object per (session, source) per process: a chain's head
|
|
219
|
-
* lives in it, so two objects for the same chain would both start at
|
|
220
|
-
* seq 0 and fork it. Closed sessions are forgotten; a process restart
|
|
221
|
-
* mid-session still loses the head (GAP-67).
|
|
222
|
-
*/
|
|
223
|
-
private readonly attached;
|
|
224
|
-
/** Buyer sessions by the host's own key (GAP-71). */
|
|
225
|
-
private readonly opened;
|
|
226
|
-
private retryAt;
|
|
227
|
-
constructor(deps: SessionsDeps);
|
|
228
|
-
/**
|
|
229
|
-
* Buyer half: the evidence session for a key of the host's own (its
|
|
230
|
-
* session, run or conversation id), opened on first use and reused
|
|
231
|
-
* after. A halted chain is reopened as a fresh session that continues
|
|
232
|
-
* the same key; a closed key is forgotten. When the platform refuses to
|
|
233
|
-
* open one, a fail-open client resolves null — the host runs without
|
|
234
|
-
* evidence — until `openRetryMs` has passed (GAP-71); otherwise the
|
|
235
|
-
* refusal is thrown and the next call tries again. The identity is
|
|
236
|
-
* required either way: that is configuration.
|
|
237
|
-
*/
|
|
238
|
-
open(key: string, input?: OpenSessionInput): Promise<Session | null>;
|
|
239
|
-
private forget;
|
|
240
|
-
private openFresh;
|
|
241
|
-
/** Buyer half: create an AGENT_TRACE session bound to the agent identity, then announce it on the chain. */
|
|
242
|
-
start(input?: StartSessionInput): Promise<Session>;
|
|
243
|
-
private identityFor;
|
|
244
|
-
private create;
|
|
245
|
-
/** Seller half: emit INTERNAL_NETWORK evidence into a session the buyer bound, or open a seller-born one. */
|
|
246
|
-
ensure(sessionId?: string | null): Promise<Session>;
|
|
247
|
-
private attach;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export { type AgentIdentity as A, BelticApiError as B, ChainRejectedError as C, DEFAULT_OPEN_RETRY_MS as D, type OpenSessionInput as O, type RedactFn as R, Session as S, type ToolCallSpan as T, ApiClient as a, type ApiClientOptions as b, DEFAULT_TRANSPORT as c, type SessionBorn as d, Sessions as e, type StartSessionInput as f, Transport as g, TransportClosedError as h, type TransportOptions as i, ephemeralIdentity as j, fileIdentity as k, identityFromSeed as l };
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { D as Decision } from './index-Bjs3BPPU.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The verdict as a value (Fraud Engine RFC › API: ALLOW | DENY | REVIEW).
|
|
5
|
-
* Layers combine by severity (GAP-45); a synchronous seller hook turns
|
|
6
|
-
* REVIEW into a stop or a pass according to its `onReview` (GAP-52). Both
|
|
7
|
-
* halves of the SDK and the engine share this one rule.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
type OnReview = 'abort' | 'allow';
|
|
11
|
-
declare class Verdict {
|
|
12
|
-
readonly value: Decision;
|
|
13
|
-
private constructor();
|
|
14
|
-
static readonly ALLOW: Verdict;
|
|
15
|
-
static readonly REVIEW: Verdict;
|
|
16
|
-
static readonly DENY: Verdict;
|
|
17
|
-
static of(value: Decision): Verdict;
|
|
18
|
-
/** The more severe of the two. */
|
|
19
|
-
atLeast(other: Verdict | Decision): Verdict;
|
|
20
|
-
/** Whether a synchronous gate must stop the call (GAP-52). */
|
|
21
|
-
blocks(onReview: OnReview): boolean;
|
|
22
|
-
/** What the gate effectively did: DENY when it blocked, else the verdict itself. */
|
|
23
|
-
effective(onReview: OnReview): Decision;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export { type OnReview as O, Verdict as V };
|
package/dist/x402/express.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { RoutesConfig, x402ResourceServer } from '@x402/core/server';
|
|
2
|
-
import { RequestHandler } from 'express';
|
|
3
|
-
import { B as Beltic } from '../client-C-mV_3A0.js';
|
|
4
|
-
import { G as GuardedMiddlewareOptions } from '../middleware-BwAYpBTl.js';
|
|
5
|
-
export { a as attachX402 } from '../adapter-CF-cUYSA.js';
|
|
6
|
-
import '../index-Bjs3BPPU.js';
|
|
7
|
-
import 'zod';
|
|
8
|
-
import '../verdict-BAahb5po.js';
|
|
9
|
-
import '../session-5TClPLI4.js';
|
|
10
|
-
|
|
11
|
-
/** Seller half for express: `@x402/express`'s payment middleware with the Beltic hooks attached. */
|
|
12
|
-
|
|
13
|
-
declare function belticPaymentMiddleware(beltic: Beltic, routes: RoutesConfig, server: x402ResourceServer, opts?: GuardedMiddlewareOptions): RequestHandler;
|
|
14
|
-
|
|
15
|
-
export { belticPaymentMiddleware };
|