@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.
Files changed (37) hide show
  1. package/README.md +19 -4
  2. package/dist/gateway/caller-auth-gateway.d.ts +103 -2
  3. package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
  4. package/dist/gateway/caller-auth-gateway.js +176 -19
  5. package/dist/gateway/caller-auth-gateway.js.map +1 -1
  6. package/dist/gateway/http-server.d.ts +12 -0
  7. package/dist/gateway/http-server.d.ts.map +1 -1
  8. package/dist/gateway/http-server.js +45 -1
  9. package/dist/gateway/http-server.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/wallet/autonomous-wallet-store.d.ts +123 -0
  15. package/dist/wallet/autonomous-wallet-store.d.ts.map +1 -0
  16. package/dist/wallet/autonomous-wallet-store.js +318 -0
  17. package/dist/wallet/autonomous-wallet-store.js.map +1 -0
  18. package/dist/wallet/autonomous-wallet.d.ts +14 -39
  19. package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
  20. package/dist/wallet/autonomous-wallet.js +12 -145
  21. package/dist/wallet/autonomous-wallet.js.map +1 -1
  22. package/dist/wallet/encrypted-file-credential-store.d.ts +41 -0
  23. package/dist/wallet/encrypted-file-credential-store.d.ts.map +1 -0
  24. package/dist/wallet/encrypted-file-credential-store.js +221 -0
  25. package/dist/wallet/encrypted-file-credential-store.js.map +1 -0
  26. package/dist/wallet/secret-service-probe.d.ts +56 -0
  27. package/dist/wallet/secret-service-probe.d.ts.map +1 -0
  28. package/dist/wallet/secret-service-probe.js +407 -0
  29. package/dist/wallet/secret-service-probe.js.map +1 -0
  30. package/package.json +1 -1
  31. package/src/gateway/caller-auth-gateway.ts +281 -15
  32. package/src/gateway/http-server.ts +64 -0
  33. package/src/index.ts +19 -0
  34. package/src/wallet/autonomous-wallet-store.ts +487 -0
  35. package/src/wallet/autonomous-wallet.ts +57 -224
  36. package/src/wallet/encrypted-file-credential-store.ts +341 -0
  37. 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. See
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 next on-chain read
302
- fails closed with no extra bookkeeping.
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 streamReader;
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":"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"}
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
- const stream = await metrik.getStreamV2(streamId);
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
- streamReader;
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
- this.streamReader =
89
- config.streamReader ??
90
- createSdkStreamReader({
91
- escrowAddress: config.escrowAddress,
92
- rpcUrl: config.rpcUrl,
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
- let stream;
146
- try {
147
- stream = await this.streamReader.getStream(capability.streamId);
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
- catch {
150
- return deny("stream-not-found", 403, capability);
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 deny("buyer-mismatch", 403, capability);
287
+ return "buyer-mismatch";
154
288
  }
155
289
  if (stream.serviceRef.toLowerCase() !== capability.serviceRef.toLowerCase()) {
156
- return deny("service-ref-mismatch", 403, capability);
290
+ return "service-ref-mismatch";
157
291
  }
158
292
  if (stream.status !== "active") {
159
- return deny("stream-not-active", 403, capability);
293
+ return "stream-not-active";
160
294
  }
161
295
  if (nowSeconds >= stream.expiresAt) {
162
- return deny("stream-expired", 403, capability);
296
+ return "stream-expired";
163
297
  }
164
298
  if (stream.deposit <= stream.claimedCumulative) {
165
- return deny("stream-not-funded", 402, capability);
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,KAAK,EAA0B,MAAM,MAAM,CAAC;AAEhE,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,iCAAiC,GAGlC,MAAM,wCAAwC,CAAC;AA8DhD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,EAAE,CAAC;AAEtD,uFAAuF;AACvF,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAElD;;;;GAIG;AACH,MAAM,iBAAiB,GAAsC;IAC3D,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,sBAAsB;IACtB,mBAAmB;IACnB,oBAAoB;IACpB,kBAAkB;CACnB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,gBAAgB,GAAwC,IAAI,GAAG,CAAC;IACpE,mBAAmB;IACnB,mBAAmB;CACpB,CAAC,CAAC;AAoDH;;;;;GAKG;AACH,MAAM,OAAO,2BAA2B;IAGT;IAFZ,OAAO,GAAG,IAAI,GAAG,EAAkC,CAAC;IAErE,YAA6B,aAAa,MAAM;QAAnB,eAAU,GAAV,UAAU,CAAS;IAAG,CAAC;IAEpD,GAAG,CAAC,QAAa;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,CAAC,QAAa,EAAE,MAA8B;QAClD,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAY,OAAe,EAAE,OAAsC;QACjE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,iGAAiG;AACjG,MAAM,UAAU,qBAAqB,CAAC,OAGrC;IACC,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC;QACtC,MAAM,EAAE,OAAO,CAAC,aAAa;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,QAAQ;YACtB,IAAI,CAAC;gBACH,qEAAqE;gBACrE,6DAA6D;gBAC7D,uEAAuE;gBACvE,oEAAoE;gBACpE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;oBACxC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC;oBAC5B,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;iBACrD,CAAC,CAAC;gBACH,OAAO;oBACL,KAAK,EAAE,MAAM,CAAC,KAAK;oBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;oBAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;oBAC3C,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,UAAU,EAAE;wBACV,WAAW,EAAE,KAAK,CAAC,MAAM;wBACzB,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;qBACxC;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,yBAAyB,CACjC,yBAAyB,QAAQ,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC9F,EAAE,KAAK,EAAE,CACV,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAQD;;;;GAIG;AACH,MAAM,OAAO,wBAAwB;IAClB,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAElD,OAAO,CAAC,KAAU,EAAE,gBAAwB;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK;QACX,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACjD,KAAK,MAAM,CAAC,GAAG,EAAE,gBAAgB,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAChD,IAAI,gBAAgB,GAAG,UAAU,EAAE,CAAC;gBAClC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAqDD;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IACX,aAAa,CAA0B;IACvC,wBAAwB,CAAS;IACjC,aAAa,CAAsB;IACnC,UAAU,CAAmB;IAC7B,UAAU,CAAS;IACnB,MAAM,CAAkC;IACxC,WAAW,CAAsB;IACjC,GAAG,CAAe;IAEnC,YAAY,MAA+B;QACzC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;gBACrE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,UAAU,GAAG,CAChB,MAAM,CAAC,UAAU,IAAI,sBAAsB,CAC5C,CAAC,WAAW,EAAE,CAAC;QAChB,MAAM,aAAa,GACjB,MAAM,CAAC,YAAY;YACnB,qBAAqB,CAAC;gBACpB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,MAAM,EAAE,MAAM,CAAC,MAAgB;aAChC,CAAC,CAAC;QACL,MAAM,aAAa,GACjB,MAAM,CAAC,0BAA0B;YACjC,CAAC,MAAM,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACjD,qBAAqB,CAAC;gBACpB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,MAAM;aACP,CAAC,CACH,CAAC;QACJ,IAAI,aAAa,CAAC,MAAM,GAAG,gCAAgC,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CACb,WAAW,gCAAgC,gEAAgE,CAC5G,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,CAAC,aAAa,EAAE,GAAG,aAAa,CAAC,CAAC;QAEvD,MAAM,YAAY,GAChB,MAAM,CAAC,wBAAwB,IAAI,mCAAmC,CAAC;QACzE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,wBAAwB,GAAG,YAAY,CAAC;QAC7C,IAAI,CAAC,aAAa;YAChB,MAAM,CAAC,aAAa,IAAI,IAAI,2BAA2B,EAAE,CAAC;QAC5D,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,IAAI,wBAAwB,EAAE,CAAC;QACtE,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;YAChC,iBAAiB,EAAE,MAAM,CAAC,aAAa;SACxC,CAAC;QACF,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,SAAS,CACb,OAA+B;QAE/B,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACnE,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,UAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,UAAU,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,4BAA4B,EAAE,CAAC;gBAClD,OAAO,IAAI,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;YAClD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE9B,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,iCAAiC,CAC9C,UAAU,EACV,IAAI,CAAC,MAAM,EACX,UAAU,CAAC,SAAgB,CAC5B,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;YACrE,OAAO,IAAI,CAAC,iBAAiB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1D,IAAI,gBAAgB,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,eAAe,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAChD,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC/D,OAAO,IAAI,CAAC,sBAAsB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACvD,CAAC;QAED,sEAAsE;QACtE,0EAA0E;QAC1E,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,KAAY,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACzE,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAe,CAAC;QAE5C,wEAAwE;QACxE,0EAA0E;QAC1E,gBAAgB;QAChB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;QAC3D,CAAC;QAED,4EAA4E;QAC5E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAC/D,CAAC;QAEF,0EAA0E;QAC1E,uEAAuE;QACvE,8CAA8C;QAC9C,MAAM,OAAO,GAA6B,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAwB,EAAE,CAAC;QACtC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACjC,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YACvE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAAC;QACzD,CAAC;QAED,uDAAuD;QACvD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACvE,CAAC;IAED,4FAA4F;IACpF,YAAY,CAClB,MAAyB,EACzB,UAAsC,EACtC,UAAkB;QAElB,2EAA2E;QAC3E,qDAAqD;QACrD,IACE,MAAM,CAAC,UAAU,KAAK,SAAS;YAC/B,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,cAAc;gBAC3C,IAAI,CAAC,wBAAwB,EAC/B,CAAC;YACD,OAAO,oBAAoB,CAAC;QAC9B,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAClE,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QACD,IACE,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,EACvE,CAAC;YACD,OAAO,sBAAsB,CAAC;QAChC,CAAC;QACD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,IAAI,UAAU,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACnC,OAAO,gBAAgB,CAAC;QAC1B,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC/C,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAED,SAAS,aAAa,CAAC,MAA8B;IACnD,OAAO,MAAM,KAAK,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACpD,CAAC;AAED,SAAS,eAAe,CACtB,OAA0C;IAE1C,KAAK,MAAM,SAAS,IAAI,iBAAiB,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAA2B,CAAC;AAC9C,CAAC;AAED,SAAS,YAAY,CAAC,KAAmC;IACvD,IAAI,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAsB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;QAC/C,IACE,SAAS,KAAK,SAAS;YACvB,CAAC,OAAO,KAAK,SAAS,IAAI,SAAS,GAAG,OAAO,CAAC,EAC9C,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,IAAI,CACX,MAA8B,EAC9B,UAAqB,EACrB,UAAuC;IAEvC,OAAO;QACL,UAAU,EAAE,KAAK;QACjB,MAAM;QACN,UAAU;QACV,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,OAAqD,EACrD,IAAY;IAEZ,+EAA+E;IAC/E,mEAAmE;IACnE,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -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,EAElB,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;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,0BAA0B,CAqD5B;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,CAkBnE"}
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,