@absol-labs/agent 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -4
- package/dist/gateway/caller-auth-gateway.d.ts +103 -2
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +176 -19
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +12 -0
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +45 -1
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/wallet/autonomous-wallet-store.d.ts +123 -0
- package/dist/wallet/autonomous-wallet-store.d.ts.map +1 -0
- package/dist/wallet/autonomous-wallet-store.js +318 -0
- package/dist/wallet/autonomous-wallet-store.js.map +1 -0
- package/dist/wallet/autonomous-wallet.d.ts +14 -39
- package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet.js +12 -145
- package/dist/wallet/autonomous-wallet.js.map +1 -1
- package/dist/wallet/encrypted-file-credential-store.d.ts +41 -0
- package/dist/wallet/encrypted-file-credential-store.d.ts.map +1 -0
- package/dist/wallet/encrypted-file-credential-store.js +221 -0
- package/dist/wallet/encrypted-file-credential-store.js.map +1 -0
- package/dist/wallet/secret-service-probe.d.ts +56 -0
- package/dist/wallet/secret-service-probe.d.ts.map +1 -0
- package/dist/wallet/secret-service-probe.js +407 -0
- package/dist/wallet/secret-service-probe.js.map +1 -0
- package/package.json +1 -1
- package/src/gateway/caller-auth-gateway.ts +281 -15
- package/src/gateway/http-server.ts +64 -0
- package/src/index.ts +19 -0
- package/src/wallet/autonomous-wallet-store.ts +487 -0
- package/src/wallet/autonomous-wallet.ts +57 -224
- package/src/wallet/encrypted-file-credential-store.ts +341 -0
- package/src/wallet/secret-service-probe.ts +487 -0
package/README.md
CHANGED
|
@@ -74,7 +74,9 @@ For a fresh autonomous agent, the default headless path is
|
|
|
74
74
|
stores it in the host OS credential manager, and asks the public Metrik broker to create a
|
|
75
75
|
policy-bound Privy EOA owned by that key. No Privy secret, OTP, browser, clipboard, or
|
|
76
76
|
plaintext key file is required, and every later write is signed locally over the exact
|
|
77
|
-
prepared Privy request.
|
|
77
|
+
prepared Privy request. Provisioning refuses a credential store that would not survive a
|
|
78
|
+
host reboot — including the Linux kernel keyring a headless host silently falls back to —
|
|
79
|
+
and ships `EncryptedFileCredentialStore` as the durable headless option. See
|
|
78
80
|
[`docs/autonomous-privy-wallet.md`](./docs/autonomous-privy-wallet.md). The authenticated
|
|
79
81
|
user-owned Privy flow remains available as an optional recoverable mode.
|
|
80
82
|
|
|
@@ -288,7 +290,9 @@ await server.listen(8787);
|
|
|
288
290
|
Or run the ready-made standalone server from env (`METRIK_GATEWAY_ESCROW_ADDRESS`,
|
|
289
291
|
`METRIK_GATEWAY_RPC_URL`, `METRIK_GATEWAY_SERVICE_REF`, `METRIK_GATEWAY_UPSTREAM_URL`,
|
|
290
292
|
optional comma-separated `METRIK_GATEWAY_SERVICE_REFS` migration aliases,
|
|
291
|
-
optional `METRIK_GATEWAY_CHAIN_ID` / `METRIK_GATEWAY_PORT` / `METRIK_GATEWAY_HOST
|
|
293
|
+
optional `METRIK_GATEWAY_CHAIN_ID` / `METRIK_GATEWAY_PORT` / `METRIK_GATEWAY_HOST`,
|
|
294
|
+
optional `METRIK_GATEWAY_CORROBORATING_RPC_URLS` /
|
|
295
|
+
`METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS`):
|
|
292
296
|
|
|
293
297
|
```bash
|
|
294
298
|
pnpm gateway
|
|
@@ -298,8 +302,19 @@ Every request must carry a valid capability; every failure mode (missing header,
|
|
|
298
302
|
signature, wrong buyer, closed/expired/underfunded stream, replayed nonce, wrong
|
|
299
303
|
method/path, wrong `serviceRef`) is rejected with a distinct machine-readable `reason`
|
|
300
304
|
and a `402`/`403` - the real upstream is never touched on a rejection. Access is revoked
|
|
301
|
-
automatically: once a stream is closed, expired, or reclaimed, the
|
|
302
|
-
|
|
305
|
+
automatically: once a stream is closed, expired, or reclaimed, the on-chain read fails
|
|
306
|
+
closed with no extra bookkeeping.
|
|
307
|
+
|
|
308
|
+
Stream state is never trusted from a single unverified view. Every configured RPC view is
|
|
309
|
+
read per request (in parallel, at most one read each) and a request is authorized only if
|
|
310
|
+
**every** view authorizes - so a stale view cannot keep serving a stream the buyer just
|
|
311
|
+
closed. A view reporting a chain head older than
|
|
312
|
+
`METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS` (default 30) is rejected outright
|
|
313
|
+
(`stream-state-stale`), and because `close`/expiry/full-claim are irreversible on-chain,
|
|
314
|
+
an observed terminal state is remembered for the process lifetime - a later stale
|
|
315
|
+
`active` read can never re-authorize. Set
|
|
316
|
+
`METRIK_GATEWAY_CORROBORATING_RPC_URLS` to one or more **independent** providers to
|
|
317
|
+
collapse the post-close window to the freshest of them.
|
|
303
318
|
|
|
304
319
|
**Buyer side** - after `hireVerifiedService`/`open()`, call the purchased service
|
|
305
320
|
directly:
|
|
@@ -11,9 +11,48 @@ import { type SignedInvocationCapability } from "../capability/invocation-capabi
|
|
|
11
11
|
* called. Revocation is automatic: once a stream is closed/expired/reclaimed,
|
|
12
12
|
* the on-chain read step below fails closed and access stops with no extra
|
|
13
13
|
* bookkeeping.
|
|
14
|
+
*
|
|
15
|
+
* ## Stream state must never be trusted from a single unverified view (#87)
|
|
16
|
+
*
|
|
17
|
+
* A capability presented seconds after the buyer's `close()` was mined was
|
|
18
|
+
* served, because authorization read the stream from ONE unpinned `latest`
|
|
19
|
+
* view and believed it unconditionally: the exposure window was exactly
|
|
20
|
+
* "however stale that view happened to be" - unbounded and unobservable.
|
|
21
|
+
* Provider replica lag, an unsafe-head reorg, provider response caching, or a
|
|
22
|
+
* cache added later for performance all land in the same failure mode, and it
|
|
23
|
+
* fails OPEN on the one transition that must be immediate.
|
|
24
|
+
*
|
|
25
|
+
* Three fail-closed properties remove that trust:
|
|
26
|
+
*
|
|
27
|
+
* 1. **Corroboration** - every configured view is read (bounded: one read per
|
|
28
|
+
* view, in parallel) and the request is authorized ONLY if EVERY view
|
|
29
|
+
* authorizes. Any view reporting a non-authorizable stream - or failing to
|
|
30
|
+
* read at all - denies. Independent endpoints go stale independently, so
|
|
31
|
+
* configuring one corroborating RPC collapses the window to the freshest of
|
|
32
|
+
* them.
|
|
33
|
+
* 2. **Freshness bound** - a view that reports the block it observed
|
|
34
|
+
* ({@link GatewayStreamView.observedAt}) is rejected outright when that
|
|
35
|
+
* block is older than {@link CallerAuthGatewayConfig.maxStateStalenessSeconds},
|
|
36
|
+
* turning silent staleness into an explicit `stream-state-stale` denial.
|
|
37
|
+
* 3. **Monotonic revocation** - `StreamEscrowV2` only ever assigns
|
|
38
|
+
* `status = Closed` (never resets it), only ever decreases `deposit` (there
|
|
39
|
+
* is no top-up), and fixes `expiresAt` at open. "Not active", "expired" and
|
|
40
|
+
* "fully claimed" are therefore irreversible, so an observed terminal state
|
|
41
|
+
* is remembered and a later view reporting ACTIVE - which is provably stale
|
|
42
|
+
* - can never re-authorize. This is the only correctness-preserving caching
|
|
43
|
+
* direction here: negative, never positive.
|
|
14
44
|
*/
|
|
15
45
|
/** Machine-readable, closed set of rejection reasons - every failure mode is distinct. */
|
|
16
|
-
export type CallerAuthDenialReason = "missing-capability-header" | "malformed-capability-header" | "capability-expired" | "invalid-signature" | "method-mismatch" | "path-mismatch" | "service-ref-mismatch" | "nonce-replayed" | "stream-not-found" | "buyer-mismatch" | "stream-not-active" | "stream-expired" | "stream-not-funded";
|
|
46
|
+
export type CallerAuthDenialReason = "missing-capability-header" | "malformed-capability-header" | "capability-expired" | "invalid-signature" | "method-mismatch" | "path-mismatch" | "service-ref-mismatch" | "nonce-replayed" | "stream-not-found" | "buyer-mismatch" | "stream-not-active" | "stream-expired" | "stream-not-funded" | "stream-state-stale";
|
|
47
|
+
/**
|
|
48
|
+
* Default freshness bound for on-chain stream state, in seconds. Base blocks
|
|
49
|
+
* are ~2s, so a healthy endpoint is a few seconds stale at most; this is a
|
|
50
|
+
* generous ceiling whose job is to reject GROSS staleness rather than to
|
|
51
|
+
* micro-manage a healthy provider.
|
|
52
|
+
*/
|
|
53
|
+
export declare const DEFAULT_MAX_STATE_STALENESS_SECONDS = 30;
|
|
54
|
+
/** Maximum corroborating views the bounded hot path accepts (excludes the primary). */
|
|
55
|
+
export declare const MAX_CORROBORATING_STREAM_READERS = 3;
|
|
17
56
|
export interface CallerAuthDecision {
|
|
18
57
|
readonly authorized: boolean;
|
|
19
58
|
readonly reason?: CallerAuthDenialReason;
|
|
@@ -32,11 +71,47 @@ export interface GatewayStreamView {
|
|
|
32
71
|
readonly claimedCumulative: bigint;
|
|
33
72
|
readonly expiresAt: number;
|
|
34
73
|
readonly status: "active" | "closed";
|
|
74
|
+
/**
|
|
75
|
+
* The chain head this view was observed against. Readers SHOULD report it:
|
|
76
|
+
* when present, the gateway rejects the view outright if the block is older
|
|
77
|
+
* than its freshness bound (`stream-state-stale`) instead of trusting
|
|
78
|
+
* unbounded staleness. Optional only so `StreamReader` implementations
|
|
79
|
+
* predating this field keep working; the default SDK reader always reports it.
|
|
80
|
+
*/
|
|
81
|
+
readonly observedAt?: {
|
|
82
|
+
readonly blockNumber: bigint;
|
|
83
|
+
/** Unix seconds of the observed block. */
|
|
84
|
+
readonly blockTimestamp: number;
|
|
85
|
+
};
|
|
35
86
|
}
|
|
36
87
|
/** Pluggable on-chain stream reader, so the gateway is testable without a live RPC. */
|
|
37
88
|
export interface StreamReader {
|
|
38
89
|
getStream(streamId: Hex): Promise<GatewayStreamView>;
|
|
39
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Remembers streams observed in an irreversible terminal state, so a later
|
|
93
|
+
* stale view cannot re-authorize them. Negative-only by construction: nothing
|
|
94
|
+
* that would GRANT access is ever cached.
|
|
95
|
+
*/
|
|
96
|
+
export interface StreamRevocationSet {
|
|
97
|
+
/** The remembered terminal denial for this stream, if any. */
|
|
98
|
+
get(streamId: Hex): CallerAuthDenialReason | undefined;
|
|
99
|
+
/** Records an irreversible terminal denial for this stream. */
|
|
100
|
+
record(streamId: Hex, reason: CallerAuthDenialReason): void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* In-memory {@link StreamRevocationSet}. Bounded (oldest entries are evicted
|
|
104
|
+
* past {@link maxEntries}) so a hostile caller cannot grow it without limit;
|
|
105
|
+
* eviction is safe because the on-chain read still denies an evicted stream -
|
|
106
|
+
* it only loses the short-circuit.
|
|
107
|
+
*/
|
|
108
|
+
export declare class InMemoryStreamRevocationSet implements StreamRevocationSet {
|
|
109
|
+
private readonly maxEntries;
|
|
110
|
+
private readonly revoked;
|
|
111
|
+
constructor(maxEntries?: number);
|
|
112
|
+
get(streamId: Hex): CallerAuthDenialReason | undefined;
|
|
113
|
+
record(streamId: Hex, reason: CallerAuthDenialReason): void;
|
|
114
|
+
}
|
|
40
115
|
export declare class UnknownStreamGatewayError extends Error {
|
|
41
116
|
constructor(message: string, options?: {
|
|
42
117
|
readonly cause?: unknown;
|
|
@@ -77,6 +152,28 @@ export interface CallerAuthGatewayConfig {
|
|
|
77
152
|
readonly headerName?: string;
|
|
78
153
|
/** Override the on-chain reader (tests inject a fake; default is the real SDK reader). */
|
|
79
154
|
readonly streamReader?: StreamReader;
|
|
155
|
+
/**
|
|
156
|
+
* Independent corroborating views of the SAME escrow. Every view is read per
|
|
157
|
+
* request (in parallel) and the request is authorized only if EVERY view
|
|
158
|
+
* authorizes - so a stale primary cannot serve a closed stream. Bounded to
|
|
159
|
+
* {@link MAX_CORROBORATING_STREAM_READERS}.
|
|
160
|
+
*/
|
|
161
|
+
readonly corroboratingStreamReaders?: readonly StreamReader[];
|
|
162
|
+
/**
|
|
163
|
+
* Corroborating RPC endpoints for the default SDK reader path. One reader is
|
|
164
|
+
* built per URL; ignored when `corroboratingStreamReaders` is supplied.
|
|
165
|
+
* Use endpoints on DIFFERENT providers - two URLs on one provider share its
|
|
166
|
+
* staleness.
|
|
167
|
+
*/
|
|
168
|
+
readonly corroboratingRpcUrls?: readonly string[];
|
|
169
|
+
/**
|
|
170
|
+
* Reject stream state observed more than this many seconds behind the wall
|
|
171
|
+
* clock. Default {@link DEFAULT_MAX_STATE_STALENESS_SECONDS}. Enforced only
|
|
172
|
+
* for views that report {@link GatewayStreamView.observedAt}.
|
|
173
|
+
*/
|
|
174
|
+
readonly maxStateStalenessSeconds?: number;
|
|
175
|
+
/** Override the terminal-state memory (default in-memory, bounded). */
|
|
176
|
+
readonly revocationSet?: StreamRevocationSet;
|
|
80
177
|
/** Override the replay cache (tests inject a fake; default is in-memory). */
|
|
81
178
|
readonly nonceCache?: NonceReplayCache;
|
|
82
179
|
/** Injectable clock (unix seconds), for tests. */
|
|
@@ -96,7 +193,9 @@ export interface CallerAuthRequestInput {
|
|
|
96
193
|
* See `./http-server.ts` for a ready-to-run reverse-proxy reference server.
|
|
97
194
|
*/
|
|
98
195
|
export declare class CallerAuthGateway {
|
|
99
|
-
private readonly
|
|
196
|
+
private readonly streamReaders;
|
|
197
|
+
private readonly maxStateStalenessSeconds;
|
|
198
|
+
private readonly revocationSet;
|
|
100
199
|
private readonly nonceCache;
|
|
101
200
|
private readonly headerName;
|
|
102
201
|
private readonly domain;
|
|
@@ -104,5 +203,7 @@ export declare class CallerAuthGateway {
|
|
|
104
203
|
private readonly now;
|
|
105
204
|
constructor(config: CallerAuthGatewayConfig);
|
|
106
205
|
authorize(request: CallerAuthRequestInput): Promise<CallerAuthDecision>;
|
|
206
|
+
/** Returns the denial reason this single view produces, or `undefined` if it authorizes. */
|
|
207
|
+
private evaluateView;
|
|
107
208
|
}
|
|
108
209
|
//# sourceMappingURL=caller-auth-gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caller-auth-gateway.d.ts","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhE,OAAO,EAOL,KAAK,0BAA0B,EAChC,MAAM,wCAAwC,CAAC;AAEhD
|
|
1
|
+
{"version":3,"file":"caller-auth-gateway.d.ts","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
import { MetrikClient } from "@absol-labs/sdk";
|
|
2
2
|
import { isAddress, isHex } from "viem";
|
|
3
3
|
import { CAPABILITY_HEADER_NAME, decodeCapabilityHeader, hashInvocationPath, InvalidCapabilityHeaderError, recoverInvocationCapabilitySigner, } from "../capability/invocation-capability.js";
|
|
4
|
+
/**
|
|
5
|
+
* Default freshness bound for on-chain stream state, in seconds. Base blocks
|
|
6
|
+
* are ~2s, so a healthy endpoint is a few seconds stale at most; this is a
|
|
7
|
+
* generous ceiling whose job is to reject GROSS staleness rather than to
|
|
8
|
+
* micro-manage a healthy provider.
|
|
9
|
+
*/
|
|
10
|
+
export const DEFAULT_MAX_STATE_STALENESS_SECONDS = 30;
|
|
11
|
+
/** Maximum corroborating views the bounded hot path accepts (excludes the primary). */
|
|
12
|
+
export const MAX_CORROBORATING_STREAM_READERS = 3;
|
|
13
|
+
/**
|
|
14
|
+
* Denial precedence when views disagree: the most authoritative statement about
|
|
15
|
+
* the stream wins, so a single fresh "closed" is never masked by another view's
|
|
16
|
+
* read error or staleness.
|
|
17
|
+
*/
|
|
18
|
+
const DENIAL_PRECEDENCE = [
|
|
19
|
+
"stream-not-active",
|
|
20
|
+
"stream-expired",
|
|
21
|
+
"buyer-mismatch",
|
|
22
|
+
"service-ref-mismatch",
|
|
23
|
+
"stream-not-funded",
|
|
24
|
+
"stream-state-stale",
|
|
25
|
+
"stream-not-found",
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Denials that reflect an IRREVERSIBLE on-chain state (see the class docs):
|
|
29
|
+
* once observed, they hold forever, so they are remembered and a stale ACTIVE
|
|
30
|
+
* read can never re-authorize.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately limited to states derived PURELY from on-chain values. Expiry is
|
|
33
|
+
* equally irreversible but is derived from the local clock, and a skewed clock
|
|
34
|
+
* must not be able to permanently revoke a live stream - expiry re-denies on
|
|
35
|
+
* every request anyway, at no extra cost.
|
|
36
|
+
*/
|
|
37
|
+
const TERMINAL_DENIALS = new Set([
|
|
38
|
+
"stream-not-active",
|
|
39
|
+
"stream-not-funded",
|
|
40
|
+
]);
|
|
41
|
+
/**
|
|
42
|
+
* In-memory {@link StreamRevocationSet}. Bounded (oldest entries are evicted
|
|
43
|
+
* past {@link maxEntries}) so a hostile caller cannot grow it without limit;
|
|
44
|
+
* eviction is safe because the on-chain read still denies an evicted stream -
|
|
45
|
+
* it only loses the short-circuit.
|
|
46
|
+
*/
|
|
47
|
+
export class InMemoryStreamRevocationSet {
|
|
48
|
+
maxEntries;
|
|
49
|
+
revoked = new Map();
|
|
50
|
+
constructor(maxEntries = 10_000) {
|
|
51
|
+
this.maxEntries = maxEntries;
|
|
52
|
+
}
|
|
53
|
+
get(streamId) {
|
|
54
|
+
return this.revoked.get(streamId.toLowerCase());
|
|
55
|
+
}
|
|
56
|
+
record(streamId, reason) {
|
|
57
|
+
const key = streamId.toLowerCase();
|
|
58
|
+
if (this.revoked.has(key)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (this.revoked.size >= this.maxEntries) {
|
|
62
|
+
const oldest = this.revoked.keys().next();
|
|
63
|
+
if (!oldest.done) {
|
|
64
|
+
this.revoked.delete(oldest.value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
this.revoked.set(key, reason);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
4
70
|
export class UnknownStreamGatewayError extends Error {
|
|
5
71
|
constructor(message, options) {
|
|
6
72
|
super(message, options);
|
|
@@ -16,7 +82,14 @@ export function createSdkStreamReader(options) {
|
|
|
16
82
|
return {
|
|
17
83
|
async getStream(streamId) {
|
|
18
84
|
try {
|
|
19
|
-
|
|
85
|
+
// Read the stream and the chain head this endpoint is serving in one
|
|
86
|
+
// round trip (concurrent, same transport) so the view can be
|
|
87
|
+
// freshness-checked. A failed head read is treated as an unusable view
|
|
88
|
+
// (fail closed) rather than silently dropping the freshness signal.
|
|
89
|
+
const [stream, block] = await Promise.all([
|
|
90
|
+
metrik.getStreamV2(streamId),
|
|
91
|
+
metrik.publicClient.getBlock({ blockTag: "latest" }),
|
|
92
|
+
]);
|
|
20
93
|
return {
|
|
21
94
|
buyer: stream.buyer,
|
|
22
95
|
serviceRef: stream.serviceRef,
|
|
@@ -24,6 +97,10 @@ export function createSdkStreamReader(options) {
|
|
|
24
97
|
claimedCumulative: stream.claimedCumulative,
|
|
25
98
|
expiresAt: stream.expiresAt,
|
|
26
99
|
status: stream.status,
|
|
100
|
+
observedAt: {
|
|
101
|
+
blockNumber: block.number,
|
|
102
|
+
blockTimestamp: Number(block.timestamp),
|
|
103
|
+
},
|
|
27
104
|
};
|
|
28
105
|
}
|
|
29
106
|
catch (cause) {
|
|
@@ -64,7 +141,9 @@ export class InMemoryNonceReplayCache {
|
|
|
64
141
|
* See `./http-server.ts` for a ready-to-run reverse-proxy reference server.
|
|
65
142
|
*/
|
|
66
143
|
export class CallerAuthGateway {
|
|
67
|
-
|
|
144
|
+
streamReaders;
|
|
145
|
+
maxStateStalenessSeconds;
|
|
146
|
+
revocationSet;
|
|
68
147
|
nonceCache;
|
|
69
148
|
headerName;
|
|
70
149
|
domain;
|
|
@@ -85,12 +164,27 @@ export class CallerAuthGateway {
|
|
|
85
164
|
}
|
|
86
165
|
this.serviceRefs = new Set(serviceRefs.map((value) => value.toLowerCase()));
|
|
87
166
|
this.headerName = (config.headerName ?? CAPABILITY_HEADER_NAME).toLowerCase();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
167
|
+
const primaryReader = config.streamReader ??
|
|
168
|
+
createSdkStreamReader({
|
|
169
|
+
escrowAddress: config.escrowAddress,
|
|
170
|
+
rpcUrl: config.rpcUrl,
|
|
171
|
+
});
|
|
172
|
+
const corroborating = config.corroboratingStreamReaders ??
|
|
173
|
+
(config.corroboratingRpcUrls ?? []).map((rpcUrl) => createSdkStreamReader({
|
|
174
|
+
escrowAddress: config.escrowAddress,
|
|
175
|
+
rpcUrl,
|
|
176
|
+
}));
|
|
177
|
+
if (corroborating.length > MAX_CORROBORATING_STREAM_READERS) {
|
|
178
|
+
throw new Error(`at most ${MAX_CORROBORATING_STREAM_READERS} corroborating stream readers are supported (bounded hot path)`);
|
|
179
|
+
}
|
|
180
|
+
this.streamReaders = [primaryReader, ...corroborating];
|
|
181
|
+
const maxStaleness = config.maxStateStalenessSeconds ?? DEFAULT_MAX_STATE_STALENESS_SECONDS;
|
|
182
|
+
if (!Number.isFinite(maxStaleness) || maxStaleness <= 0) {
|
|
183
|
+
throw new Error("maxStateStalenessSeconds must be a positive number");
|
|
184
|
+
}
|
|
185
|
+
this.maxStateStalenessSeconds = maxStaleness;
|
|
186
|
+
this.revocationSet =
|
|
187
|
+
config.revocationSet ?? new InMemoryStreamRevocationSet();
|
|
94
188
|
this.nonceCache = config.nonceCache ?? new InMemoryNonceReplayCache();
|
|
95
189
|
this.domain = {
|
|
96
190
|
chainId: config.chainId ?? 84532,
|
|
@@ -142,30 +236,93 @@ export class CallerAuthGateway {
|
|
|
142
236
|
if (!this.nonceCache.consume(capability.nonce, capability.expiry)) {
|
|
143
237
|
return deny("nonce-replayed", 403, capability);
|
|
144
238
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
239
|
+
const streamId = capability.streamId;
|
|
240
|
+
// An irreversible terminal state already observed for this stream holds
|
|
241
|
+
// forever: no read can un-close it, so short-circuit (and never re-read a
|
|
242
|
+
// dead stream).
|
|
243
|
+
const revoked = this.revocationSet.get(streamId);
|
|
244
|
+
if (revoked !== undefined) {
|
|
245
|
+
return deny(revoked, httpStatusFor(revoked), capability);
|
|
148
246
|
}
|
|
149
|
-
|
|
150
|
-
|
|
247
|
+
// Read EVERY configured view (bounded: one read per view, all in parallel).
|
|
248
|
+
const results = await Promise.allSettled(this.streamReaders.map((reader) => reader.getStream(streamId)));
|
|
249
|
+
// Strictest view wins. A view that fails to read, is measurably stale, or
|
|
250
|
+
// reports a non-authorizable stream denies the request - authorization
|
|
251
|
+
// requires unanimous consent from every view.
|
|
252
|
+
const denials = [];
|
|
253
|
+
const views = [];
|
|
254
|
+
for (const result of results) {
|
|
255
|
+
if (result.status === "rejected") {
|
|
256
|
+
denials.push("stream-not-found");
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const reason = this.evaluateView(result.value, capability, nowSeconds);
|
|
260
|
+
if (reason === undefined) {
|
|
261
|
+
views.push(result.value);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
denials.push(reason);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (denials.length > 0) {
|
|
268
|
+
const reason = strictestDenial(denials);
|
|
269
|
+
if (TERMINAL_DENIALS.has(reason)) {
|
|
270
|
+
this.revocationSet.record(streamId, reason);
|
|
271
|
+
}
|
|
272
|
+
return deny(reason, httpStatusFor(reason), capability);
|
|
273
|
+
}
|
|
274
|
+
// Report the freshest corroborated view to the caller.
|
|
275
|
+
return { authorized: true, stream: freshestView(views), capability };
|
|
276
|
+
}
|
|
277
|
+
/** Returns the denial reason this single view produces, or `undefined` if it authorizes. */
|
|
278
|
+
evaluateView(stream, capability, nowSeconds) {
|
|
279
|
+
// Freshness first: a measurably stale view is not evidence of anything, so
|
|
280
|
+
// it must not be able to vouch for an ACTIVE stream.
|
|
281
|
+
if (stream.observedAt !== undefined &&
|
|
282
|
+
nowSeconds - stream.observedAt.blockTimestamp >
|
|
283
|
+
this.maxStateStalenessSeconds) {
|
|
284
|
+
return "stream-state-stale";
|
|
151
285
|
}
|
|
152
286
|
if (stream.buyer.toLowerCase() !== capability.buyer.toLowerCase()) {
|
|
153
|
-
return
|
|
287
|
+
return "buyer-mismatch";
|
|
154
288
|
}
|
|
155
289
|
if (stream.serviceRef.toLowerCase() !== capability.serviceRef.toLowerCase()) {
|
|
156
|
-
return
|
|
290
|
+
return "service-ref-mismatch";
|
|
157
291
|
}
|
|
158
292
|
if (stream.status !== "active") {
|
|
159
|
-
return
|
|
293
|
+
return "stream-not-active";
|
|
160
294
|
}
|
|
161
295
|
if (nowSeconds >= stream.expiresAt) {
|
|
162
|
-
return
|
|
296
|
+
return "stream-expired";
|
|
163
297
|
}
|
|
164
298
|
if (stream.deposit <= stream.claimedCumulative) {
|
|
165
|
-
return
|
|
299
|
+
return "stream-not-funded";
|
|
300
|
+
}
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function httpStatusFor(reason) {
|
|
305
|
+
return reason === "stream-not-funded" ? 402 : 403;
|
|
306
|
+
}
|
|
307
|
+
function strictestDenial(denials) {
|
|
308
|
+
for (const candidate of DENIAL_PRECEDENCE) {
|
|
309
|
+
if (denials.includes(candidate)) {
|
|
310
|
+
return candidate;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return denials[0];
|
|
314
|
+
}
|
|
315
|
+
function freshestView(views) {
|
|
316
|
+
let freshest = views[0];
|
|
317
|
+
for (const view of views.slice(1)) {
|
|
318
|
+
const current = freshest.observedAt?.blockNumber;
|
|
319
|
+
const candidate = view.observedAt?.blockNumber;
|
|
320
|
+
if (candidate !== undefined &&
|
|
321
|
+
(current === undefined || candidate > current)) {
|
|
322
|
+
freshest = view;
|
|
166
323
|
}
|
|
167
|
-
return { authorized: true, stream, capability };
|
|
168
324
|
}
|
|
325
|
+
return freshest;
|
|
169
326
|
}
|
|
170
327
|
function deny(reason, httpStatus, capability) {
|
|
171
328
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caller-auth-gateway.js","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"caller-auth-gateway.js","sourceRoot":"","sources":["../../src/gateway/caller-auth-gateway.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,10 @@ export interface CallerAuthGatewayEnvConfig {
|
|
|
27
27
|
readonly chainId: number;
|
|
28
28
|
readonly upstreamUrl: string;
|
|
29
29
|
readonly headerName?: string;
|
|
30
|
+
/** Independent RPCs used to corroborate stream state (see `CallerAuthGateway`). */
|
|
31
|
+
readonly corroboratingRpcUrls: readonly string[];
|
|
32
|
+
/** Freshness bound for on-chain stream state, in seconds. */
|
|
33
|
+
readonly maxStateStalenessSeconds: number;
|
|
30
34
|
}
|
|
31
35
|
/**
|
|
32
36
|
* Parses the gateway's env contract:
|
|
@@ -36,6 +40,14 @@ export interface CallerAuthGatewayEnvConfig {
|
|
|
36
40
|
* - `METRIK_GATEWAY_SERVICE_REF` (required) - primary bytes32 service ref.
|
|
37
41
|
* - `METRIK_GATEWAY_SERVICE_REFS` (optional) - comma-separated migration aliases.
|
|
38
42
|
* - `METRIK_GATEWAY_UPSTREAM_URL` (required) - the real service to proxy to on pass.
|
|
43
|
+
* - `METRIK_GATEWAY_CORROBORATING_RPC_URLS` (optional, STRONGLY recommended) -
|
|
44
|
+
* comma-separated INDEPENDENT RPC endpoints for the same escrow. Stream state
|
|
45
|
+
* is authorized only if every configured view agrees, so a stale primary view
|
|
46
|
+
* cannot serve a stream that has just been closed. At most
|
|
47
|
+
* {@link MAX_CORROBORATING_STREAM_READERS}.
|
|
48
|
+
* - `METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS` (optional) - reject stream
|
|
49
|
+
* state observed more than N seconds behind the wall clock. Default
|
|
50
|
+
* {@link DEFAULT_MAX_STATE_STALENESS_SECONDS}.
|
|
39
51
|
* - `METRIK_GATEWAY_CHAIN_ID` (optional) - default `84532` (Base Sepolia).
|
|
40
52
|
* - `METRIK_GATEWAY_HEADER_NAME` (optional) - default `x-metrik-capability`.
|
|
41
53
|
* - `PORT` / `METRIK_GATEWAY_PORT` (optional) - default `8787`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/gateway/http-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EAEZ,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAoB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhE,OAAO,EACL,iBAAiB,
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../../src/gateway/http-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EAEZ,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAoB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhE,OAAO,EACL,iBAAiB,EAIlB,MAAM,0BAA0B,CAAC;AA8BlC,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,uBAAuB,CAsCzB;AAmID,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,6DAA6D;IAC7D,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,0BAA0B,CA4F5B;AAUD,oFAAoF;AACpF,wBAAsB,mCAAmC,CACvD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,uBAAuB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BnE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createServer, } from "node:http";
|
|
2
2
|
import { isAddress, isHex } from "viem";
|
|
3
|
-
import { CallerAuthGateway, } from "./caller-auth-gateway.js";
|
|
3
|
+
import { CallerAuthGateway, DEFAULT_MAX_STATE_STALENESS_SECONDS, MAX_CORROBORATING_STREAM_READERS, } from "./caller-auth-gateway.js";
|
|
4
4
|
/**
|
|
5
5
|
* Reference standalone reverse-proxy gateway server (metrik-agent#63).
|
|
6
6
|
*
|
|
@@ -156,6 +156,14 @@ function logError(context, error) {
|
|
|
156
156
|
* - `METRIK_GATEWAY_SERVICE_REF` (required) - primary bytes32 service ref.
|
|
157
157
|
* - `METRIK_GATEWAY_SERVICE_REFS` (optional) - comma-separated migration aliases.
|
|
158
158
|
* - `METRIK_GATEWAY_UPSTREAM_URL` (required) - the real service to proxy to on pass.
|
|
159
|
+
* - `METRIK_GATEWAY_CORROBORATING_RPC_URLS` (optional, STRONGLY recommended) -
|
|
160
|
+
* comma-separated INDEPENDENT RPC endpoints for the same escrow. Stream state
|
|
161
|
+
* is authorized only if every configured view agrees, so a stale primary view
|
|
162
|
+
* cannot serve a stream that has just been closed. At most
|
|
163
|
+
* {@link MAX_CORROBORATING_STREAM_READERS}.
|
|
164
|
+
* - `METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS` (optional) - reject stream
|
|
165
|
+
* state observed more than N seconds behind the wall clock. Default
|
|
166
|
+
* {@link DEFAULT_MAX_STATE_STALENESS_SECONDS}.
|
|
159
167
|
* - `METRIK_GATEWAY_CHAIN_ID` (optional) - default `84532` (Base Sepolia).
|
|
160
168
|
* - `METRIK_GATEWAY_HEADER_NAME` (optional) - default `x-metrik-capability`.
|
|
161
169
|
* - `PORT` / `METRIK_GATEWAY_PORT` (optional) - default `8787`.
|
|
@@ -197,6 +205,31 @@ export function parseCallerAuthGatewayEnvConfig(env = process.env) {
|
|
|
197
205
|
}
|
|
198
206
|
const host = env.METRIK_GATEWAY_HOST ?? "0.0.0.0";
|
|
199
207
|
const headerName = env.METRIK_GATEWAY_HEADER_NAME;
|
|
208
|
+
const corroboratingRpcUrls = [
|
|
209
|
+
...new Set((env.METRIK_GATEWAY_CORROBORATING_RPC_URLS ?? "")
|
|
210
|
+
.split(",")
|
|
211
|
+
.map((value) => value.trim())
|
|
212
|
+
.filter((value) => value.length > 0)),
|
|
213
|
+
];
|
|
214
|
+
for (const candidate of corroboratingRpcUrls) {
|
|
215
|
+
try {
|
|
216
|
+
// eslint-disable-next-line no-new -- validates the URL is well-formed.
|
|
217
|
+
new URL(candidate);
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
throw new Error(`METRIK_GATEWAY_CORROBORATING_RPC_URLS must contain only valid URLs (got ${candidate})`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (corroboratingRpcUrls.length > MAX_CORROBORATING_STREAM_READERS) {
|
|
224
|
+
throw new Error(`METRIK_GATEWAY_CORROBORATING_RPC_URLS accepts at most ${MAX_CORROBORATING_STREAM_READERS} URLs (bounded hot path)`);
|
|
225
|
+
}
|
|
226
|
+
const stalenessRaw = env.METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS ??
|
|
227
|
+
String(DEFAULT_MAX_STATE_STALENESS_SECONDS);
|
|
228
|
+
const maxStateStalenessSeconds = Number(stalenessRaw);
|
|
229
|
+
if (!Number.isInteger(maxStateStalenessSeconds) ||
|
|
230
|
+
maxStateStalenessSeconds <= 0) {
|
|
231
|
+
throw new Error(`invalid METRIK_GATEWAY_MAX_STATE_STALENESS_SECONDS: ${stalenessRaw}`);
|
|
232
|
+
}
|
|
200
233
|
return {
|
|
201
234
|
host,
|
|
202
235
|
port,
|
|
@@ -208,6 +241,8 @@ export function parseCallerAuthGatewayEnvConfig(env = process.env) {
|
|
|
208
241
|
],
|
|
209
242
|
chainId,
|
|
210
243
|
upstreamUrl,
|
|
244
|
+
corroboratingRpcUrls,
|
|
245
|
+
maxStateStalenessSeconds,
|
|
211
246
|
...(headerName === undefined ? {} : { headerName }),
|
|
212
247
|
};
|
|
213
248
|
}
|
|
@@ -227,10 +262,19 @@ export async function startCallerAuthGatewayServerFromEnv(env = process.env) {
|
|
|
227
262
|
serviceRef: config.serviceRef,
|
|
228
263
|
serviceRefs: config.serviceRefs,
|
|
229
264
|
chainId: config.chainId,
|
|
265
|
+
corroboratingRpcUrls: config.corroboratingRpcUrls,
|
|
266
|
+
maxStateStalenessSeconds: config.maxStateStalenessSeconds,
|
|
230
267
|
...(config.headerName === undefined
|
|
231
268
|
? {}
|
|
232
269
|
: { headerName: config.headerName }),
|
|
233
270
|
});
|
|
271
|
+
if (config.corroboratingRpcUrls.length === 0) {
|
|
272
|
+
console.error("[metrik-caller-auth-gateway] WARNING: no METRIK_GATEWAY_CORROBORATING_RPC_URLS " +
|
|
273
|
+
"configured — stream state is authorized from a single RPC view. A stale view " +
|
|
274
|
+
"can authorize a stream that has just been closed (bounded to " +
|
|
275
|
+
`${config.maxStateStalenessSeconds}s by the freshness check). Configure at least ` +
|
|
276
|
+
"one INDEPENDENT provider to close that window.");
|
|
277
|
+
}
|
|
234
278
|
const server = createCallerAuthGatewayServer({
|
|
235
279
|
gateway,
|
|
236
280
|
upstreamUrl: config.upstreamUrl,
|