@agirails/sdk 4.4.9 → 4.5.2

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 (93) hide show
  1. package/dist/builders/DeliveryProofBuilder.d.ts +224 -13
  2. package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
  3. package/dist/builders/DeliveryProofBuilder.js +247 -13
  4. package/dist/builders/DeliveryProofBuilder.js.map +1 -1
  5. package/dist/cli/agirails.d.ts +85 -1
  6. package/dist/cli/agirails.d.ts.map +1 -1
  7. package/dist/cli/agirails.js +429 -154
  8. package/dist/cli/agirails.js.map +1 -1
  9. package/dist/cli/commands/init.d.ts +54 -0
  10. package/dist/cli/commands/init.d.ts.map +1 -1
  11. package/dist/cli/commands/init.js +193 -1
  12. package/dist/cli/commands/init.js.map +1 -1
  13. package/dist/cli/commands/receipt.d.ts +70 -2
  14. package/dist/cli/commands/receipt.d.ts.map +1 -1
  15. package/dist/cli/commands/receipt.js +218 -3
  16. package/dist/cli/commands/receipt.js.map +1 -1
  17. package/dist/cli/commands/test.d.ts +77 -1
  18. package/dist/cli/commands/test.d.ts.map +1 -1
  19. package/dist/cli/commands/test.js +264 -2
  20. package/dist/cli/commands/test.js.map +1 -1
  21. package/dist/cli/lib/runRequest.d.ts +90 -0
  22. package/dist/cli/lib/runRequest.d.ts.map +1 -1
  23. package/dist/cli/lib/runRequest.js +300 -9
  24. package/dist/cli/lib/runRequest.js.map +1 -1
  25. package/dist/cli/lib/sentinelReflections.d.ts +111 -0
  26. package/dist/cli/lib/sentinelReflections.d.ts.map +1 -0
  27. package/dist/cli/lib/sentinelReflections.js +193 -0
  28. package/dist/cli/lib/sentinelReflections.js.map +1 -0
  29. package/dist/delivery/MockDeliveryChannel.d.ts +208 -0
  30. package/dist/delivery/MockDeliveryChannel.d.ts.map +1 -0
  31. package/dist/delivery/MockDeliveryChannel.js +445 -0
  32. package/dist/delivery/MockDeliveryChannel.js.map +1 -0
  33. package/dist/delivery/RelayDeliveryChannel.d.ts +176 -0
  34. package/dist/delivery/RelayDeliveryChannel.d.ts.map +1 -0
  35. package/dist/delivery/RelayDeliveryChannel.js +377 -0
  36. package/dist/delivery/RelayDeliveryChannel.js.map +1 -0
  37. package/dist/delivery/channel.d.ts +282 -0
  38. package/dist/delivery/channel.d.ts.map +1 -0
  39. package/dist/delivery/channel.js +76 -0
  40. package/dist/delivery/channel.js.map +1 -0
  41. package/dist/delivery/channelLog.d.ts +115 -0
  42. package/dist/delivery/channelLog.d.ts.map +1 -0
  43. package/dist/delivery/channelLog.js +94 -0
  44. package/dist/delivery/channelLog.js.map +1 -0
  45. package/dist/delivery/crypto.d.ts +312 -0
  46. package/dist/delivery/crypto.d.ts.map +1 -0
  47. package/dist/delivery/crypto.js +495 -0
  48. package/dist/delivery/crypto.js.map +1 -0
  49. package/dist/delivery/eip712.d.ts +248 -0
  50. package/dist/delivery/eip712.d.ts.map +1 -0
  51. package/dist/delivery/eip712.js +397 -0
  52. package/dist/delivery/eip712.js.map +1 -0
  53. package/dist/delivery/envelopeBuilder.d.ts +531 -0
  54. package/dist/delivery/envelopeBuilder.d.ts.map +1 -0
  55. package/dist/delivery/envelopeBuilder.js +832 -0
  56. package/dist/delivery/envelopeBuilder.js.map +1 -0
  57. package/dist/delivery/index.d.ts +53 -0
  58. package/dist/delivery/index.d.ts.map +1 -0
  59. package/dist/delivery/index.js +143 -0
  60. package/dist/delivery/index.js.map +1 -0
  61. package/dist/delivery/keys.d.ts +344 -0
  62. package/dist/delivery/keys.d.ts.map +1 -0
  63. package/dist/delivery/keys.js +513 -0
  64. package/dist/delivery/keys.js.map +1 -0
  65. package/dist/delivery/nonce-keys.d.ts +93 -0
  66. package/dist/delivery/nonce-keys.d.ts.map +1 -0
  67. package/dist/delivery/nonce-keys.js +88 -0
  68. package/dist/delivery/nonce-keys.js.map +1 -0
  69. package/dist/delivery/setupBuilder.d.ts +403 -0
  70. package/dist/delivery/setupBuilder.d.ts.map +1 -0
  71. package/dist/delivery/setupBuilder.js +554 -0
  72. package/dist/delivery/setupBuilder.js.map +1 -0
  73. package/dist/delivery/types.d.ts +722 -0
  74. package/dist/delivery/types.d.ts.map +1 -0
  75. package/dist/delivery/types.js +150 -0
  76. package/dist/delivery/types.js.map +1 -0
  77. package/dist/delivery/validate.d.ts +288 -0
  78. package/dist/delivery/validate.d.ts.map +1 -0
  79. package/dist/delivery/validate.js +648 -0
  80. package/dist/delivery/validate.js.map +1 -0
  81. package/dist/level1/Agent.d.ts +130 -0
  82. package/dist/level1/Agent.d.ts.map +1 -1
  83. package/dist/level1/Agent.js +248 -0
  84. package/dist/level1/Agent.js.map +1 -1
  85. package/dist/level1/types/Options.d.ts +62 -0
  86. package/dist/level1/types/Options.d.ts.map +1 -1
  87. package/dist/level1/types/Options.js +22 -0
  88. package/dist/level1/types/Options.js.map +1 -1
  89. package/dist/runtime/MockRuntime.d.ts +32 -0
  90. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  91. package/dist/runtime/MockRuntime.js +44 -0
  92. package/dist/runtime/MockRuntime.js.map +1 -1
  93. package/package.json +6 -1
@@ -0,0 +1,377 @@
1
+ "use strict";
2
+ /**
3
+ * AIP-16 Delivery Surface — RelayDeliveryChannel (Phase 2b)
4
+ * ===========================================================
5
+ *
6
+ * HTTP-backed {@link DeliveryChannel} implementation that talks to the
7
+ * AGIRAILS relay (or any compatible relay implementing the same REST
8
+ * surface) for posting and observing delivery setup + envelope wire
9
+ * objects.
10
+ *
11
+ * Mirrors the design of `src/negotiation/RelayChannel.ts`:
12
+ *
13
+ * - POST / GET endpoints follow the same `/api/v1/delivery/...` shape
14
+ * as the negotiation relay's `/api/v1/negotiations/...` endpoints.
15
+ * - Subscriptions poll on a fixed interval (1000ms by default — slightly
16
+ * faster than negotiation since delivery is the final-mile step the
17
+ * requester is actively waiting on).
18
+ * - Cursor pagination on GETs so a polling subscriber only sees new
19
+ * items per tick.
20
+ * - SSRF guard on `baseUrl` so a misconfigured agent cannot be steered
21
+ * at cloud-metadata services, RFC1918 hosts, or loopback addresses
22
+ * in production. `allowPrivateHosts: true` bypasses for dev / tests.
23
+ * - 8-second timeout on every POST + GET via AbortController so a
24
+ * hung relay cannot wedge the SDK indefinitely.
25
+ * - Dedup-after-verify on read: each item is verified BEFORE its
26
+ * identifier is added to the dedup set. An attacker who posts a
27
+ * valid-looking-but-malformed wire to the relay cannot poison the
28
+ * dedup set and suppress later legitimate items.
29
+ * - Subscriber errors are caught + logged so one bad subscriber cannot
30
+ * halt the polling loop.
31
+ *
32
+ * @module delivery/RelayDeliveryChannel
33
+ * @see {@link DeliveryChannel}
34
+ * @see ../negotiation/RelayChannel — reference pattern this mirrors.
35
+ */
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.RelayDeliveryChannel = exports.REQUEST_TIMEOUT_MS = exports.POLL_INTERVAL_MS = void 0;
38
+ const QuoteChannel_1 = require("../transport/QuoteChannel");
39
+ const channelLog_1 = require("./channelLog");
40
+ const envelopeBuilder_1 = require("./envelopeBuilder");
41
+ const setupBuilder_1 = require("./setupBuilder");
42
+ // ============================================================================
43
+ // Constants
44
+ // ============================================================================
45
+ /**
46
+ * Default polling cadence for `subscribeSetups` / `subscribeEnvelopes`,
47
+ * in milliseconds. 1000ms balances snappy delivery (p95 latency below 1s
48
+ * per round trip) against poll-amplification cost when many parallel
49
+ * subscriptions are armed.
50
+ */
51
+ exports.POLL_INTERVAL_MS = 1000;
52
+ /**
53
+ * Default request timeout for POSTs and GETs to the relay, in milliseconds.
54
+ * 8000ms is short enough that a hung relay surfaces quickly but long
55
+ * enough that genuinely slow networks (mobile, satellite) don't
56
+ * spurious-abort under normal load.
57
+ */
58
+ exports.REQUEST_TIMEOUT_MS = 8000;
59
+ /** Default base URL — production AGIRAILS relay. */
60
+ const DEFAULT_BASE_URL = 'https://agirails.app';
61
+ // ============================================================================
62
+ // RelayDeliveryChannel
63
+ // ============================================================================
64
+ /**
65
+ * HTTP relay-backed delivery channel. Production transport for AIP-16
66
+ * setups + envelopes.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const channel = new RelayDeliveryChannel({
71
+ * baseUrl: 'https://agirails.app',
72
+ * });
73
+ * await channel.publishSetup(setupWire);
74
+ * const sub = await channel.subscribeEnvelopes(txId, async (env) => {
75
+ * await processEnvelope(env);
76
+ * });
77
+ * // …later
78
+ * await sub.close();
79
+ * await channel.close();
80
+ * ```
81
+ */
82
+ class RelayDeliveryChannel {
83
+ constructor(opts = {}) {
84
+ this.pollStates = new Set();
85
+ this.closed = false;
86
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
87
+ (0, QuoteChannel_1.assertSafePeerUrl)(this.baseUrl, opts.allowPrivateHosts ?? false);
88
+ this.pollIntervalMs = opts.pollIntervalMs ?? exports.POLL_INTERVAL_MS;
89
+ this.requestTimeoutMs = opts.requestTimeoutMs ?? exports.REQUEST_TIMEOUT_MS;
90
+ this.fetchImpl = opts.fetchImpl ?? fetch;
91
+ this.log = opts.log ?? channelLog_1.noopLog;
92
+ this.expectedKernelAddress = opts.expectedKernelAddress;
93
+ this.expectedChainId = opts.expectedChainId;
94
+ this.nowFn = opts.now;
95
+ }
96
+ // --------------------------------------------------------------------------
97
+ // publish
98
+ // --------------------------------------------------------------------------
99
+ async publishSetup(setup) {
100
+ if (this.closed) {
101
+ throw new Error('RelayDeliveryChannel: channel is closed');
102
+ }
103
+ const url = `${this.baseUrl}/api/v1/delivery/setup`;
104
+ await this.postJson(url, setup);
105
+ }
106
+ async publishEnvelope(envelope) {
107
+ if (this.closed) {
108
+ throw new Error('RelayDeliveryChannel: channel is closed');
109
+ }
110
+ const url = `${this.baseUrl}/api/v1/delivery`;
111
+ await this.postJson(url, envelope);
112
+ }
113
+ // --------------------------------------------------------------------------
114
+ // get
115
+ // --------------------------------------------------------------------------
116
+ async getSetups(txId, after) {
117
+ const url = new URL(`${this.baseUrl}/api/v1/delivery/setup/${encodeURIComponent(txId)}`);
118
+ if (after) {
119
+ url.searchParams.set('after', after);
120
+ }
121
+ const items = await this.getJson(url.toString());
122
+ return (items.items ?? []).map((item) => item.wire);
123
+ }
124
+ async getEnvelopes(txId, after) {
125
+ const url = new URL(`${this.baseUrl}/api/v1/delivery/${encodeURIComponent(txId)}`);
126
+ if (after) {
127
+ url.searchParams.set('after', after);
128
+ }
129
+ const items = await this.getJson(url.toString());
130
+ return (items.items ?? []).map((item) => item.wire);
131
+ }
132
+ // --------------------------------------------------------------------------
133
+ // subscribe
134
+ // --------------------------------------------------------------------------
135
+ async subscribeSetups(txId, callback) {
136
+ if (this.closed) {
137
+ throw new Error('RelayDeliveryChannel: channel is closed');
138
+ }
139
+ const state = {
140
+ cursor: null,
141
+ delivered: new Set(),
142
+ cancelled: false,
143
+ };
144
+ this.pollStates.add(state);
145
+ const pollOnce = async () => {
146
+ if (state.cancelled)
147
+ return;
148
+ try {
149
+ const url = new URL(`${this.baseUrl}/api/v1/delivery/setup/${encodeURIComponent(txId)}`);
150
+ if (state.cursor) {
151
+ url.searchParams.set('after', state.cursor);
152
+ }
153
+ const body = await this.getJson(url.toString());
154
+ for (const item of body.items ?? []) {
155
+ if (state.cancelled)
156
+ break;
157
+ await this.deliverSetup(item, state, callback);
158
+ state.cursor = item.cursor;
159
+ }
160
+ }
161
+ catch (err) {
162
+ const msg = err instanceof Error ? err.message : String(err);
163
+ this.log('warn', 'RelayDeliveryChannel: setup poll error', {
164
+ txId,
165
+ error: msg,
166
+ });
167
+ }
168
+ if (!state.cancelled) {
169
+ state.timer = setTimeout(pollOnce, this.pollIntervalMs);
170
+ // Allow process to exit even if subscription is still armed.
171
+ const t = state.timer;
172
+ if (typeof t.unref === 'function')
173
+ t.unref();
174
+ }
175
+ };
176
+ state.timer = setTimeout(pollOnce, 0);
177
+ const t = state.timer;
178
+ if (typeof t.unref === 'function')
179
+ t.unref();
180
+ return {
181
+ close: () => {
182
+ state.cancelled = true;
183
+ if (state.timer)
184
+ clearTimeout(state.timer);
185
+ this.pollStates.delete(state);
186
+ },
187
+ };
188
+ }
189
+ async subscribeEnvelopes(txId, callback) {
190
+ if (this.closed) {
191
+ throw new Error('RelayDeliveryChannel: channel is closed');
192
+ }
193
+ const state = {
194
+ cursor: null,
195
+ delivered: new Set(),
196
+ cancelled: false,
197
+ };
198
+ this.pollStates.add(state);
199
+ const pollOnce = async () => {
200
+ if (state.cancelled)
201
+ return;
202
+ try {
203
+ const url = new URL(`${this.baseUrl}/api/v1/delivery/${encodeURIComponent(txId)}`);
204
+ if (state.cursor) {
205
+ url.searchParams.set('after', state.cursor);
206
+ }
207
+ const body = await this.getJson(url.toString());
208
+ for (const item of body.items ?? []) {
209
+ if (state.cancelled)
210
+ break;
211
+ await this.deliverEnvelope(item, state, callback);
212
+ state.cursor = item.cursor;
213
+ }
214
+ }
215
+ catch (err) {
216
+ const msg = err instanceof Error ? err.message : String(err);
217
+ this.log('warn', 'RelayDeliveryChannel: envelope poll error', {
218
+ txId,
219
+ error: msg,
220
+ });
221
+ }
222
+ if (!state.cancelled) {
223
+ state.timer = setTimeout(pollOnce, this.pollIntervalMs);
224
+ const t = state.timer;
225
+ if (typeof t.unref === 'function')
226
+ t.unref();
227
+ }
228
+ };
229
+ state.timer = setTimeout(pollOnce, 0);
230
+ const t = state.timer;
231
+ if (typeof t.unref === 'function')
232
+ t.unref();
233
+ return {
234
+ close: () => {
235
+ state.cancelled = true;
236
+ if (state.timer)
237
+ clearTimeout(state.timer);
238
+ this.pollStates.delete(state);
239
+ },
240
+ };
241
+ }
242
+ // --------------------------------------------------------------------------
243
+ // close
244
+ // --------------------------------------------------------------------------
245
+ async close() {
246
+ this.closed = true;
247
+ for (const state of this.pollStates) {
248
+ state.cancelled = true;
249
+ if (state.timer)
250
+ clearTimeout(state.timer);
251
+ }
252
+ this.pollStates.clear();
253
+ }
254
+ // --------------------------------------------------------------------------
255
+ // Internals
256
+ // --------------------------------------------------------------------------
257
+ /**
258
+ * Deliver a single setup item — verify, dedup-after-verify, isolate
259
+ * subscriber errors.
260
+ */
261
+ async deliverSetup(item, state, callback) {
262
+ // Verify FIRST — dedup AFTER verify so a malformed sig cannot
263
+ // poison the dedup set.
264
+ const verifyResult = setupBuilder_1.DeliverySetupBuilder.verify(item.wire, {
265
+ expectedKernelAddress: this.expectedKernelAddress ?? item.wire.signed.kernelAddress,
266
+ expectedChainId: this.expectedChainId ?? item.wire.signed.chainId,
267
+ now: this.nowFn?.(),
268
+ });
269
+ if (!verifyResult.ok) {
270
+ this.log('warn', 'RelayDeliveryChannel: dropping unverified setup', {
271
+ code: verifyResult.code,
272
+ error: verifyResult.error,
273
+ txId: item.wire.signed.txId,
274
+ });
275
+ return;
276
+ }
277
+ const hash = setupBuilder_1.DeliverySetupBuilder.computeHash(item.wire);
278
+ if (state.delivered.has(hash))
279
+ return;
280
+ state.delivered.add(hash);
281
+ try {
282
+ await callback(item.wire);
283
+ }
284
+ catch (err) {
285
+ const msg = err instanceof Error ? err.message : String(err);
286
+ this.log('warn', 'RelayDeliveryChannel: setup subscriber threw', {
287
+ error: msg,
288
+ txId: item.wire.signed.txId,
289
+ });
290
+ }
291
+ }
292
+ /**
293
+ * Deliver a single envelope item — verify, dedup-after-verify, isolate
294
+ * subscriber errors.
295
+ */
296
+ async deliverEnvelope(item, state, callback) {
297
+ const verifyResult = envelopeBuilder_1.DeliveryEnvelopeBuilder.verify(item.wire, {
298
+ expectedKernelAddress: this.expectedKernelAddress ?? item.wire.signed.kernelAddress,
299
+ expectedChainId: this.expectedChainId ?? item.wire.signed.chainId,
300
+ now: this.nowFn?.(),
301
+ });
302
+ if (!verifyResult.ok) {
303
+ this.log('warn', 'RelayDeliveryChannel: dropping unverified envelope', {
304
+ code: verifyResult.code,
305
+ error: verifyResult.error,
306
+ txId: item.wire.signed.txId,
307
+ });
308
+ return;
309
+ }
310
+ const hash = envelopeBuilder_1.DeliveryEnvelopeBuilder.computeHash(item.wire);
311
+ if (state.delivered.has(hash))
312
+ return;
313
+ state.delivered.add(hash);
314
+ try {
315
+ await callback(item.wire);
316
+ }
317
+ catch (err) {
318
+ const msg = err instanceof Error ? err.message : String(err);
319
+ this.log('warn', 'RelayDeliveryChannel: envelope subscriber threw', {
320
+ error: msg,
321
+ txId: item.wire.signed.txId,
322
+ });
323
+ }
324
+ }
325
+ /**
326
+ * Issue a POST with JSON body and an AbortController-driven timeout.
327
+ * Resolves on 2xx, rejects on non-2xx with the response body as the
328
+ * error message.
329
+ */
330
+ async postJson(url, body) {
331
+ const controller = new AbortController();
332
+ const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
333
+ try {
334
+ const res = await this.fetchImpl(url, {
335
+ method: 'POST',
336
+ headers: { 'Content-Type': 'application/json' },
337
+ body: JSON.stringify(body),
338
+ signal: controller.signal,
339
+ });
340
+ if (!res.ok) {
341
+ const text = await res.text().catch(() => '');
342
+ this.log('warn', 'RelayDeliveryChannel: POST non-2xx', {
343
+ url,
344
+ status: res.status,
345
+ body: text.slice(0, 256),
346
+ });
347
+ throw new Error(`RelayDeliveryChannel POST ${res.status}: ${text.slice(0, 200)}`);
348
+ }
349
+ }
350
+ finally {
351
+ clearTimeout(timer);
352
+ }
353
+ }
354
+ /**
355
+ * Issue a GET and decode JSON, with an AbortController-driven timeout.
356
+ */
357
+ async getJson(url) {
358
+ const controller = new AbortController();
359
+ const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
360
+ try {
361
+ const res = await this.fetchImpl(url, {
362
+ method: 'GET',
363
+ signal: controller.signal,
364
+ });
365
+ if (!res.ok) {
366
+ const text = await res.text().catch(() => '');
367
+ throw new Error(`RelayDeliveryChannel GET ${res.status}: ${text.slice(0, 200)}`);
368
+ }
369
+ return (await res.json());
370
+ }
371
+ finally {
372
+ clearTimeout(timer);
373
+ }
374
+ }
375
+ }
376
+ exports.RelayDeliveryChannel = RelayDeliveryChannel;
377
+ //# sourceMappingURL=RelayDeliveryChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RelayDeliveryChannel.js","sourceRoot":"","sources":["../../src/delivery/RelayDeliveryChannel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,282 @@
1
+ /**
2
+ * AIP-16 Delivery Surface — Channel Abstraction (Phase 2b)
3
+ * =========================================================
4
+ *
5
+ * Transport-agnostic interface for posting and observing delivery
6
+ * setup + envelope wire objects between requester and provider.
7
+ *
8
+ * The delivery channel is the wire-level boundary between the two
9
+ * participants of an AIP-16 delivery exchange. It does NOT participate
10
+ * in any cryptographic verification — its only job is to transport
11
+ * already-signed {@link DeliverySetupWireV1} and {@link DeliveryEnvelopeWireV1}
12
+ * objects between participants.
13
+ *
14
+ * ## Concrete implementations
15
+ *
16
+ * - **MockDeliveryChannel** — in-process loopback used by tests and
17
+ * MockRuntime flows. Implements dedup-after-verify on the read side
18
+ * (see {@link MockChannel} in `src/negotiation/` for the reference
19
+ * pattern). Useful for end-to-end tests without network setup.
20
+ * - **RelayDeliveryChannel** — HTTP client against the AGIRAILS relay
21
+ * (or any compatible relay implementing the same REST surface). Uses
22
+ * cursor pagination, polling at `POLL_INTERVAL_MS = 1000`, and an
23
+ * SSRF guard on the relay URL (see {@link RelayChannel} in
24
+ * `src/negotiation/` for the reference pattern).
25
+ *
26
+ * ## Security invariants (binding on ALL implementations)
27
+ *
28
+ * 1. **Dedup AFTER verify.** Implementations that deduplicate
29
+ * incoming setups/envelopes MUST verify signatures BEFORE adding any
30
+ * identifier (txId, sig hash, etc.) to a dedup set. Otherwise an
31
+ * attacker can post malformed signatures to permanently suppress
32
+ * the legitimate signed object that arrives later.
33
+ *
34
+ * 2. **Subscriber error isolation.** Subscriber callbacks may throw
35
+ * arbitrary errors (consumer code is not the channel's problem).
36
+ * Implementations MUST catch and silently swallow callback errors —
37
+ * NEVER propagate them into the channel's read loop, since one bad
38
+ * subscriber would otherwise halt delivery for all other subscribers
39
+ * sharing the same channel.
40
+ *
41
+ * 3. **No verification at the channel layer.** Channels do NOT call
42
+ * `recoverSetupSigner` / `recoverEnvelopeSigner` or any other
43
+ * cryptographic check. Verification is the consumer's responsibility
44
+ * (typically via {@link DeliverySetupBuilder.verify} /
45
+ * {@link DeliveryEnvelopeBuilder.verify}). The channel is a dumb pipe.
46
+ *
47
+ * 4. **Address comparison case-insensitivity.** Where addresses appear
48
+ * in dedup keys (e.g. `signerAddress`), implementations MUST normalize
49
+ * to lowercase on both sides of any comparison.
50
+ *
51
+ * ## Subscription semantics
52
+ *
53
+ * - `subscribeSetups` / `subscribeEnvelopes` are scoped to a single
54
+ * `txId`. A subscription begins emitting from "now" — that is, from
55
+ * objects that are NOT already known to the channel at subscribe time
56
+ * are guaranteed to be delivered; objects that ARE already known MAY
57
+ * or MAY NOT be re-delivered depending on the implementation. Code
58
+ * that needs the full historical set should call the optional
59
+ * `getSetups` / `getEnvelopes` methods.
60
+ *
61
+ * - Returning a {@link DeliverySubscription} whose `close()` is invoked
62
+ * MUST stop further callbacks from firing on that subscription. It
63
+ * SHOULD also free any underlying transport (polling timer, HTTP
64
+ * connection, etc.).
65
+ *
66
+ * - Multiple subscribers on the same `txId` MUST each receive all
67
+ * matching objects (fan-out, not steal). One subscriber's `close()`
68
+ * MUST NOT affect other subscribers.
69
+ *
70
+ * @module delivery/channel
71
+ * @see {@link DeliverySetupWireV1}
72
+ * @see {@link DeliveryEnvelopeWireV1}
73
+ */
74
+ import type { DeliverySetupWireV1, DeliveryEnvelopeWireV1 } from './types';
75
+ /**
76
+ * Handle returned from a `subscribe*` call. Calling `close()` cancels
77
+ * the subscription — the corresponding callback will not fire again.
78
+ *
79
+ * `close()` is idempotent: calling it multiple times is safe and a no-op
80
+ * after the first call. It MAY return a Promise (e.g. when the
81
+ * implementation needs to await an in-flight HTTP request); callers
82
+ * SHOULD `await` it when they need to confirm teardown completed
83
+ * before, e.g., asserting that no further callbacks fire.
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const sub = await channel.subscribeEnvelopes(txId, async (env) => {
88
+ * await processEnvelope(env);
89
+ * });
90
+ * // …later
91
+ * await sub.close();
92
+ * ```
93
+ */
94
+ export interface DeliverySubscription {
95
+ /**
96
+ * Cancel this subscription. Idempotent. MAY return a Promise that
97
+ * resolves once the underlying transport (polling timer, HTTP
98
+ * connection) has been torn down.
99
+ */
100
+ close(): void | Promise<void>;
101
+ }
102
+ /**
103
+ * Callback fired for each verified-then-deduped setup observed on the
104
+ * channel for the subscribed `txId`.
105
+ *
106
+ * NOTE: "verified-then-deduped" is the dedup-after-verify ordering
107
+ * invariant — implementations call this callback only for setups whose
108
+ * signature has been verified (and which have not already been delivered
109
+ * to this subscriber).
110
+ *
111
+ * The callback MAY be async. Errors thrown from the callback (sync or
112
+ * async) MUST be caught and swallowed by the channel implementation —
113
+ * see security invariant #2 in the module-level JSDoc.
114
+ */
115
+ export type SetupCallback = (setup: DeliverySetupWireV1) => void | Promise<void>;
116
+ /**
117
+ * Callback fired for each verified-then-deduped envelope observed on
118
+ * the channel for the subscribed `txId`.
119
+ *
120
+ * Same semantics as {@link SetupCallback}: dedup-after-verify ordering,
121
+ * may be async, errors are isolated by the channel.
122
+ */
123
+ export type EnvelopeCallback = (envelope: DeliveryEnvelopeWireV1) => void | Promise<void>;
124
+ /**
125
+ * Transport-agnostic delivery channel.
126
+ *
127
+ * Implementations are responsible for transporting already-signed
128
+ * setup and envelope wire objects between requester and provider. The
129
+ * channel does NOT verify signatures, hashes, or schemes; that is the
130
+ * caller's responsibility (see the builder `verify()` methods).
131
+ *
132
+ * ## Contract summary
133
+ *
134
+ * - `publishSetup` / `publishEnvelope` post a wire object to the
135
+ * channel. Implementations MAY perform best-effort validation (e.g.
136
+ * rejecting obviously malformed `txId` strings) but MUST NOT make
137
+ * cryptographic verification a precondition of publish — the channel
138
+ * is dumb on the write side, just as it is on the read side.
139
+ *
140
+ * - `subscribeSetups` / `subscribeEnvelopes` register a callback that
141
+ * fires for each verified-then-deduped object observed on the
142
+ * channel for the given `txId`. Returns a {@link DeliverySubscription}
143
+ * whose `close()` cancels the subscription.
144
+ *
145
+ * - `getSetups` / `getEnvelopes` (optional) return the full set of
146
+ * objects the channel currently knows about for a given `txId`.
147
+ * Useful for "catch up to current state" flows where a participant
148
+ * starts late and needs to see what was already posted. Implementations
149
+ * that cannot enumerate prior state (e.g. fire-and-forget transports)
150
+ * MAY omit these methods.
151
+ *
152
+ * - `close()` (optional) releases all channel-level resources (e.g.
153
+ * open HTTP connections, polling timers shared across subscriptions).
154
+ * Implementations that have no global state MAY omit it.
155
+ *
156
+ * @example In-process loopback (MockRuntime tests)
157
+ * ```typescript
158
+ * const channel: DeliveryChannel = new MockDeliveryChannel();
159
+ *
160
+ * await channel.publishSetup(setupWire);
161
+ * const sub = await channel.subscribeEnvelopes(txId, async (env) => {
162
+ * const result = await envelopeBuilder.verify(env);
163
+ * if (result.valid) await consumeEnvelope(env);
164
+ * });
165
+ * // …later
166
+ * await sub.close();
167
+ * ```
168
+ *
169
+ * @example HTTP relay
170
+ * ```typescript
171
+ * const channel: DeliveryChannel = new RelayDeliveryChannel({
172
+ * baseUrl: 'https://relay.agirails.io',
173
+ * relayId: 'agirails-relay-v1',
174
+ * });
175
+ * await channel.publishEnvelope(envelopeWire);
176
+ * await channel.close?.();
177
+ * ```
178
+ */
179
+ export interface DeliveryChannel {
180
+ /**
181
+ * Post a fully-signed {@link DeliverySetupWireV1} to the channel.
182
+ *
183
+ * Implementations SHOULD:
184
+ * - Perform shape validation (txId is a 32-byte hex, signature is
185
+ * 65 bytes, etc.) and reject early on obvious malformations.
186
+ * - NOT perform cryptographic verification — that is the verifier's
187
+ * job, and pushing it down into the channel layer would tie the
188
+ * transport to a specific kernel address / chainId universe.
189
+ * - Surface transport-level errors as rejected Promises with a
190
+ * structured `DeliveryError` of code `channel_post_failed` or
191
+ * `channel_unreachable`, depending on the failure class.
192
+ *
193
+ * @param setup The setup wire object to publish.
194
+ * @returns A Promise that resolves once the channel has accepted
195
+ * the publish (in a relay-backed implementation, after the relay
196
+ * acknowledges the POST; in a loopback implementation, after the
197
+ * in-memory write completes).
198
+ */
199
+ publishSetup(setup: DeliverySetupWireV1): Promise<void>;
200
+ /**
201
+ * Post a fully-signed {@link DeliveryEnvelopeWireV1} to the channel.
202
+ *
203
+ * Same contract as {@link publishSetup} — shape validation OK,
204
+ * crypto verification NOT permitted at this layer, transport errors
205
+ * surfaced as rejected Promises.
206
+ *
207
+ * @param envelope The envelope wire object to publish.
208
+ * @returns A Promise that resolves once the channel has accepted
209
+ * the publish.
210
+ */
211
+ publishEnvelope(envelope: DeliveryEnvelopeWireV1): Promise<void>;
212
+ /**
213
+ * Subscribe to setups observed on the channel for a given `txId`.
214
+ *
215
+ * The callback fires once per verified-then-deduped setup
216
+ * (dedup-after-verify ordering, see module JSDoc). Multiple
217
+ * subscriptions on the same `txId` each receive all matching
218
+ * setups (fan-out).
219
+ *
220
+ * Callback errors are isolated per security invariant #2 — the
221
+ * channel MUST catch and swallow them, never propagating into its
222
+ * own read loop or affecting other subscribers.
223
+ *
224
+ * @param txId The transaction id to scope the subscription to,
225
+ * as a `bytes32` hex-encoded string (`0x` + 64 hex chars).
226
+ * @param callback Invoked for each setup observed.
227
+ * @returns A {@link DeliverySubscription} whose `close()` cancels.
228
+ */
229
+ subscribeSetups(txId: `0x${string}`, callback: SetupCallback): Promise<DeliverySubscription>;
230
+ /**
231
+ * Subscribe to envelopes observed on the channel for a given `txId`.
232
+ *
233
+ * Same semantics as {@link subscribeSetups}.
234
+ *
235
+ * @param txId The transaction id to scope the subscription to.
236
+ * @param callback Invoked for each envelope observed.
237
+ * @returns A {@link DeliverySubscription} whose `close()` cancels.
238
+ */
239
+ subscribeEnvelopes(txId: `0x${string}`, callback: EnvelopeCallback): Promise<DeliverySubscription>;
240
+ /**
241
+ * Optional: return all setups the channel currently knows about for
242
+ * a given `txId`.
243
+ *
244
+ * Useful when a participant joins late and needs to see historical
245
+ * state. The returned array MUST be ordered by channel-observation
246
+ * order (oldest first) so callers can implement "process all then
247
+ * subscribe to new" flows deterministically.
248
+ *
249
+ * Implementations that cannot enumerate prior state (e.g.
250
+ * fire-and-forget transports, transports without server-side
251
+ * storage) MAY omit this method. Consumers MUST check for its
252
+ * presence (`if (channel.getSetups)`).
253
+ *
254
+ * @param txId The transaction id to fetch setups for.
255
+ * @returns All known setups for `txId`, oldest first.
256
+ */
257
+ getSetups?(txId: `0x${string}`): Promise<DeliverySetupWireV1[]>;
258
+ /**
259
+ * Optional: return all envelopes the channel currently knows about
260
+ * for a given `txId`. Same contract as {@link getSetups}.
261
+ *
262
+ * @param txId The transaction id to fetch envelopes for.
263
+ * @returns All known envelopes for `txId`, oldest first.
264
+ */
265
+ getEnvelopes?(txId: `0x${string}`): Promise<DeliveryEnvelopeWireV1[]>;
266
+ /**
267
+ * Optional: release any channel-level resources (HTTP connections,
268
+ * polling timers shared across subscriptions, etc.).
269
+ *
270
+ * After `close()` resolves, the channel MUST NOT fire any further
271
+ * subscriber callbacks and SHOULD reject any subsequent `publish*`
272
+ * call with `channel_unreachable`.
273
+ *
274
+ * Implementations with no global state (e.g. a pure in-memory
275
+ * loopback that closes per-subscription only) MAY omit this method.
276
+ *
277
+ * `close()` is idempotent: calling it multiple times is safe and
278
+ * a no-op after the first call.
279
+ */
280
+ close?(): void | Promise<void>;
281
+ }
282
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/delivery/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,SAAS,CAAC;AAMjB;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAMD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAM1F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;;;;;;;;;OAUG;IACH,eAAe,CAAC,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;;;;;;;;;;;;;;OAgBG;IACH,eAAe,CACb,IAAI,EAAE,KAAK,MAAM,EAAE,EACnB,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;;;;;;;OAQG;IACH,kBAAkB,CAChB,IAAI,EAAE,KAAK,MAAM,EAAE,EACnB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEjC;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEhE;;;;;;OAMG;IACH,YAAY,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC;IAEtE;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC"}