@cello-protocol/daemon 0.0.228 → 0.0.230

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 (48) hide show
  1. package/dist/channel-collect-tick.d.ts +36 -0
  2. package/dist/channel-collect-tick.d.ts.map +1 -0
  3. package/dist/channel-collect-tick.js +133 -0
  4. package/dist/channel-collect-tick.js.map +1 -0
  5. package/dist/channel-collector.d.ts +99 -0
  6. package/dist/channel-collector.d.ts.map +1 -0
  7. package/dist/channel-collector.js +249 -0
  8. package/dist/channel-collector.js.map +1 -0
  9. package/dist/channel-config-store.d.ts +33 -0
  10. package/dist/channel-config-store.d.ts.map +1 -0
  11. package/dist/channel-config-store.js +61 -0
  12. package/dist/channel-config-store.js.map +1 -0
  13. package/dist/channel-inbox-store.d.ts +46 -0
  14. package/dist/channel-inbox-store.d.ts.map +1 -0
  15. package/dist/channel-inbox-store.js +88 -0
  16. package/dist/channel-inbox-store.js.map +1 -0
  17. package/dist/channel-log-store.d.ts +14 -0
  18. package/dist/channel-log-store.d.ts.map +1 -1
  19. package/dist/channel-log-store.js +58 -0
  20. package/dist/channel-log-store.js.map +1 -1
  21. package/dist/channel-publish-handlers.d.ts +42 -0
  22. package/dist/channel-publish-handlers.d.ts.map +1 -0
  23. package/dist/channel-publish-handlers.js +212 -0
  24. package/dist/channel-publish-handlers.js.map +1 -0
  25. package/dist/channel-publish-wiring.d.ts +41 -0
  26. package/dist/channel-publish-wiring.d.ts.map +1 -0
  27. package/dist/channel-publish-wiring.js +124 -0
  28. package/dist/channel-publish-wiring.js.map +1 -0
  29. package/dist/channel-publisher.d.ts +189 -0
  30. package/dist/channel-publisher.d.ts.map +1 -0
  31. package/dist/channel-publisher.js +394 -0
  32. package/dist/channel-publisher.js.map +1 -0
  33. package/dist/channel-relay-client.d.ts +88 -0
  34. package/dist/channel-relay-client.d.ts.map +1 -0
  35. package/dist/channel-relay-client.js +180 -0
  36. package/dist/channel-relay-client.js.map +1 -0
  37. package/dist/channel-subscription-store.d.ts +66 -0
  38. package/dist/channel-subscription-store.d.ts.map +1 -0
  39. package/dist/channel-subscription-store.js +109 -0
  40. package/dist/channel-subscription-store.js.map +1 -0
  41. package/dist/daemon.d.ts.map +1 -1
  42. package/dist/daemon.js +14 -0
  43. package/dist/daemon.js.map +1 -1
  44. package/dist/gateway-config-handlers.d.ts +2 -2
  45. package/dist/gateway-config-handlers.d.ts.map +1 -1
  46. package/dist/gateway-config-handlers.js +37 -12
  47. package/dist/gateway-config-handlers.js.map +1 -1
  48. package/package.json +5 -5
@@ -0,0 +1,394 @@
1
+ import { decodeRelayPostReceipt, encodeBroadcastArtifact, encodeChannelInfo, signBroadcastArtifact, signChannelInfo, verifyRelayPostReceipt, buildChannelPruneTbs, } from "@cello-protocol/protocol-types";
2
+ /**
3
+ * Gap between deposits during a refill, so a long backlog stays under the relay's per-publisher
4
+ * rate limit. Only `resendMissing` paces — an ordinary publish is two deposits and pacing it would
5
+ * add latency to every post to protect against a burst that cannot happen.
6
+ */
7
+ export const DEFAULT_RESEND_PACE_MS = 50;
8
+ export class ChannelPublisher {
9
+ #opts;
10
+ #now;
11
+ constructor(opts) {
12
+ this.#opts = opts;
13
+ this.#now = opts.now ?? (() => Date.now());
14
+ }
15
+ async publish(agentName, channelHex, title, body, correlationId) {
16
+ const { logger, log } = this.#opts;
17
+ const info = this.#opts.channelInfo(channelHex);
18
+ if (!info)
19
+ return { ok: false, reason: "channel_unknown", detail: "no channel info for that pubkey" };
20
+ const channelKey = this.#opts.getChannelKey(channelHex);
21
+ const agentKey = this.#opts.getAgentKey(agentName);
22
+ if (!channelKey || !agentKey) {
23
+ return { ok: false, reason: "key_unavailable", detail: "the channel key or the agent key is not loaded" };
24
+ }
25
+ // 1. Screen BEFORE anything is signed or stored. The subscriber's inbound screen is the
26
+ // enforcement; this is the early check that spares an honest publisher the friction of
27
+ // publishing something every reader will refuse.
28
+ const verdict = await this.#opts.screenOutbound(new TextEncoder().encode(`${title}\n${body}`), { agentName, ...(correlationId !== undefined ? { correlationId } : {}) });
29
+ if (verdict.disposition !== "allow") {
30
+ logger.info("channel.publish.refused", {
31
+ ...(correlationId !== undefined ? { correlationId } : {}),
32
+ channel_pubkey: channelHex, disposition: verdict.disposition, reason: verdict.reason ?? "blocked",
33
+ });
34
+ return { ok: false, reason: "blocked_by_screen", detail: verdict.reason ?? verdict.disposition };
35
+ }
36
+ // 2. A public channel is readable by anyone, so encrypting it would be theatre — and would lock
37
+ // out the subscribers it exists for, who hold no key.
38
+ const plaintext = new TextEncoder().encode(body);
39
+ const wire = info.access === "public" ? plaintext : await this.#opts.encryptBody(plaintext, channelHex);
40
+ // 3. Position and signatures.
41
+ log.ensureChannel(channelHex);
42
+ const { seq } = log.nextPosition(channelHex);
43
+ let post;
44
+ try {
45
+ post = await signBroadcastArtifact(channelKey, agentKey, {
46
+ seq, published_at: this.#now(), title, body: wire, supersedes: null, ext: null,
47
+ });
48
+ }
49
+ catch (err) {
50
+ return { ok: false, reason: "post_invalid", detail: extract(err) };
51
+ }
52
+ // 4. THE LOG, BEFORE THE NETWORK.
53
+ log.append(channelHex, post, correlationId);
54
+ // 5. Both relays, in parallel — a deposit is independent of the other, and making the second
55
+ // wait on the first would double the latency of the ordinary case for no gain.
56
+ let deposited = await Promise.all(info.relays.map((relay) => this.#depositOnce(relay, post, channelHex, correlationId)));
57
+ let ok = deposited.filter((d) => d.ok);
58
+ /**
59
+ * ⚠️ **THE CLOCK-SKEW CORRECTION IS ONE POST FOR ALL RELAYS, AND ONLY WHILE NONE HAS TAKEN IT.**
60
+ *
61
+ * `published_at` is inside both signatures, so a corrected post is different BYTES at the same
62
+ * number. Correcting per relay would let relay A hold one body at seq N and relay B another —
63
+ * and a subscriber taking the union of the two sees exactly what a fork looks like, produced by
64
+ * an honest publisher with a wrong clock. So the correction happens here, once, and only when
65
+ * NO relay accepted the original: a relay that already answered holds a receipt bound to those
66
+ * bytes by hash, and re-signing under it would strand the proof.
67
+ */
68
+ if (ok.length === 0 && deposited.some((d) => d.reason === "clock_skew")) {
69
+ const corrected = await this.#resignForSkew(agentName, channelHex, post, deposited, correlationId);
70
+ if (corrected) {
71
+ post = corrected;
72
+ deposited = await Promise.all(info.relays.map((relay) => this.#depositOnce(relay, post, channelHex, correlationId)));
73
+ ok = deposited.filter((d) => d.ok);
74
+ }
75
+ }
76
+ logger.info("channel.post.published", {
77
+ ...(correlationId !== undefined ? { correlationId } : {}),
78
+ channel_pubkey: channelHex,
79
+ seq,
80
+ relays_ok: ok.map((d) => d.relay),
81
+ relays_failed: deposited.filter((d) => !d.ok).map((d) => d.relay),
82
+ });
83
+ if (ok.length === 0) {
84
+ // The post STAYS in the log. A retry must send these bytes, not a new post at a new number:
85
+ // the number and the time are inside both signatures.
86
+ return { ok: false, reason: "no_relay_accepted", seq, deposited };
87
+ }
88
+ return { ok: true, seq, deposited };
89
+ }
90
+ /**
91
+ * One deposit on one relay. No retry lives here — see the skew note in `publish`, which is where
92
+ * a correction has to happen if it is to produce the same bytes for every relay.
93
+ *
94
+ * A relay that TOOK the post is `ok: true` even when its receipt could not be filed. The two facts
95
+ * are reported separately because folding them together turned a post that is safely on two relays
96
+ * into `no_relay_accepted`, and sent the operator to resend something already there.
97
+ */
98
+ async #depositOnce(relay, post, channelHex, correlationId) {
99
+ const { logger } = this.#opts;
100
+ let answer;
101
+ try {
102
+ answer = await this.#opts.deposit(relay, { post_cbor: encodeBroadcastArtifact(post) });
103
+ }
104
+ catch (err) {
105
+ logger.warn("channel.post.deposit_failed", {
106
+ ...(correlationId !== undefined ? { correlationId } : {}),
107
+ channel_pubkey: channelHex, seq: post.seq, relay, reason: extract(err),
108
+ });
109
+ return { relay, ok: false, reason: extract(err) };
110
+ }
111
+ if (answer.ok) {
112
+ const filed = this.#storeReceipt(channelHex, post, answer.receipt_cbor, relay, correlationId);
113
+ return filed.ok ? { relay, ok: true } : { relay, ok: true, receipt_unfiled: filed.reason };
114
+ }
115
+ logger.warn("channel.post.deposit_failed", {
116
+ ...(correlationId !== undefined ? { correlationId } : {}),
117
+ channel_pubkey: channelHex, seq: post.seq, relay, reason: answer.reason,
118
+ });
119
+ return {
120
+ relay, ok: false, reason: answer.reason,
121
+ ...(answer.skew_ms !== undefined ? { skew_ms: answer.skew_ms } : {}),
122
+ };
123
+ }
124
+ /**
125
+ * Re-sign a post ONCE at a clock the relays will accept, and put the corrected bytes in the log.
126
+ *
127
+ * The correction is the LARGEST skew any relay reported: a post the fastest relay will take is one
128
+ * the others will too, and correcting to the smallest would leave the strictest relay refusing
129
+ * again with no retry left.
130
+ *
131
+ * Returns `null` when the correction cannot be made — the keys are gone, or the log refuses to
132
+ * replace bytes it has already receipted. `null` leaves the ORIGINAL post standing, which is the
133
+ * safe direction: the post is in the log at its number and `resendMissing` can carry it later.
134
+ */
135
+ async #resignForSkew(agentName, channelHex, post, deposited, correlationId) {
136
+ const { logger } = this.#opts;
137
+ const channelKey = this.#opts.getChannelKey(channelHex);
138
+ // BY NAME, from the caller. This read the empty string once, which is no agent, so the lookup
139
+ // was always null and the correction never ran in production — the test harness ignored the
140
+ // argument, so nothing said so.
141
+ const agentKey = this.#opts.getAgentKey(agentName);
142
+ if (!channelKey || !agentKey) {
143
+ logger.warn("channel.post.resign_failed", {
144
+ ...(correlationId !== undefined ? { correlationId } : {}),
145
+ channel_pubkey: channelHex, seq: post.seq, reason: "key_unavailable",
146
+ });
147
+ return null;
148
+ }
149
+ const skews = deposited.map((d) => d.skew_ms ?? 0);
150
+ const corrected = this.#now() - Math.max(...skews);
151
+ let resigned;
152
+ try {
153
+ resigned = await signBroadcastArtifact(channelKey, agentKey, {
154
+ seq: post.seq, published_at: corrected, title: post.title,
155
+ body: post.body, supersedes: post.supersedes, ext: null,
156
+ });
157
+ this.#opts.log.replaceUnreceipted(channelHex, resigned, correlationId);
158
+ }
159
+ catch (err) {
160
+ logger.warn("channel.post.resign_failed", {
161
+ ...(correlationId !== undefined ? { correlationId } : {}),
162
+ channel_pubkey: channelHex, seq: post.seq, reason: extract(err),
163
+ });
164
+ return null;
165
+ }
166
+ return resigned;
167
+ }
168
+ /** Verify a receipt against the post it names before storing it; an unverified one is worthless. */
169
+ #storeReceipt(channelHex, post, receiptCbor, relay, correlationId) {
170
+ const decoded = decodeRelayPostReceipt(receiptCbor);
171
+ if (!decoded.ok || !verifyRelayPostReceipt(decoded.receipt, post)) {
172
+ this.#opts.logger.warn("channel.post.deposit_failed", {
173
+ ...(correlationId !== undefined ? { correlationId } : {}),
174
+ channel_pubkey: channelHex, seq: post.seq, relay, reason: "receipt_invalid",
175
+ });
176
+ return { ok: false, reason: "receipt_invalid" };
177
+ }
178
+ try {
179
+ this.#opts.log.recordReceipt(channelHex, decoded.receipt, correlationId);
180
+ return { ok: true };
181
+ }
182
+ catch (err) {
183
+ // A receipt naming bytes this log does not hold. The relay DID take the post — the caller
184
+ // reports that separately, because calling the deposit failed would send the operator to
185
+ // resend a post the relay already has.
186
+ this.#opts.logger.warn("channel.post.receipt_unfiled", {
187
+ ...(correlationId !== undefined ? { correlationId } : {}),
188
+ channel_pubkey: channelHex, seq: post.seq, relay, reason: extract(err),
189
+ });
190
+ return { ok: false, reason: extract(err) };
191
+ }
192
+ }
193
+ /**
194
+ * Re-deposit everything a relay has not receipted, oldest first.
195
+ *
196
+ * This is what refills a relay that lost content and what fills a newly added one — the same path,
197
+ * which is why it is exercised by ordinary operation rather than only by a crash.
198
+ */
199
+ async resendMissing(agentName, channelHex, relay, correlationId) {
200
+ const { log, logger } = this.#opts;
201
+ // A channel that has been set up but never published has no log row yet, and `head` THROWS on
202
+ // one. Nothing to resend is an ANSWER — `deposited: 0` — not an error: a freshly created channel
203
+ // is the most likely thing an operator runs this against, and it came back looking broken.
204
+ log.ensureChannel(channelHex);
205
+ const head = log.head(channelHex);
206
+ if (head.first_seq === null || head.last_seq === null)
207
+ return { deposited: 0 };
208
+ /**
209
+ * ⚠️ WHAT THE RELAY HOLDS NOW, NOT WHAT IT ONCE RECEIPTED — and this is a deviation from the
210
+ * order, raised there.
211
+ *
212
+ * The order says to deposit "every logged post that relay has not receipted". But a receipt
213
+ * proves the relay TOOK the post once, not that it still has it — and the case the same sentence
214
+ * names, "refills a relay that lost content", is precisely a relay whose receipts are all in the
215
+ * log and whose queue is empty. Skipping on receipts refills nothing, which the enforcer caught:
216
+ * a restarted relay got 3 posts back out of 6.
217
+ *
218
+ * So the relay is asked where its queue begins and ends, and anything outside that is sent. When
219
+ * it cannot be asked, every logged post is sent — a repeat is a no-op the relay answers with the
220
+ * receipt it already signed, so the cost of over-sending is bandwidth and the cost of
221
+ * under-sending is a relay permanently missing posts.
222
+ */
223
+ let holds = null;
224
+ if (this.#opts.relayHead) {
225
+ try {
226
+ const reported = await this.#opts.relayHead(relay, channelHex);
227
+ if (reported.first_held_seq !== null && reported.last_seq !== null) {
228
+ holds = { first: reported.first_held_seq, last: reported.last_seq };
229
+ }
230
+ }
231
+ catch (err) {
232
+ logger.warn("channel.resend.head_unavailable", {
233
+ channel_pubkey: channelHex, relay, reason: extract(err),
234
+ impact: "every logged post is re-sent; a repeat is a no-op at the relay",
235
+ });
236
+ }
237
+ }
238
+ let deposited = 0;
239
+ // Oldest first: a relay's queue only accepts the next number, so any other order stalls at the
240
+ // first gap and refills nothing after it.
241
+ for (const post of log.readRange(channelHex, head.first_seq, head.last_seq)) {
242
+ if (holds !== null && post.seq >= holds.first && post.seq <= holds.last)
243
+ continue;
244
+ // PACED. A refill of a long backbone is the one path that deposits hundreds of posts in a
245
+ // row, and the relay rate-limits per publisher — so an unpaced refill trips the limiter part
246
+ // way through and the rest of the backlog is refused, which looks exactly like a relay that
247
+ // will not take the channel's posts at all.
248
+ if (deposited > 0)
249
+ await this.#pause(this.#opts.resendPaceMs ?? DEFAULT_RESEND_PACE_MS);
250
+ const outcome = await this.#depositOnce(relay, post, channelHex, correlationId);
251
+ if (outcome.ok)
252
+ deposited += 1;
253
+ }
254
+ logger.info("channel.resend.completed", {
255
+ ...(correlationId !== undefined ? { correlationId } : {}),
256
+ // WHO ran it. A refill and a prune are the two verbs that change what the world can read, and
257
+ // an operator asking "why did the backbone change" needs the acting agent in the line.
258
+ agent: agentName,
259
+ channel_pubkey: channelHex, relay, deposited,
260
+ });
261
+ return { deposited };
262
+ }
263
+ /**
264
+ * Prune the log, then tell both relays to drop the same range.
265
+ *
266
+ * ⚠️ **EACH RELAY'S OUTCOME IS THE ONE IT GAVE.** This used to report `ok: true` for every relay
267
+ * without contacting any of them, so an operator pruning 500 posts was shown two successful
268
+ * relays while both still held and served every post. A relay that is down is `ok: false` with its
269
+ * reason, and its copy survives until its own retention sweeps it — which is what retention is for.
270
+ */
271
+ async pruneChannel(agentName, channelHex, throughSeq, correlationId) {
272
+ const { logger } = this.#opts;
273
+ // Same as `resendMissing`: pruning a channel with nothing in it yet is "pruned 0", not an error.
274
+ this.#opts.log.ensureChannel(channelHex);
275
+ const { pruned } = this.#opts.log.pruneThrough(channelHex, throughSeq);
276
+ const info = this.#opts.channelInfo(channelHex);
277
+ const relays = info?.relays ?? [];
278
+ /**
279
+ * ⚠️ THE PRUNE IS SIGNED BY THE CHANNEL KEY, and it has to be: the frame is not a post, so
280
+ * nothing else proves the caller owns the channel. An unsigned prune would let anyone who knows
281
+ * a channel's public key delete its backbone from both relays.
282
+ */
283
+ const channelKey = this.#opts.getChannelKey(channelHex);
284
+ const timeMs = this.#now();
285
+ const signature = channelKey
286
+ ? await channelKey.sign(buildChannelPruneTbs(Buffer.from(channelHex, "hex"), throughSeq, timeMs))
287
+ : null;
288
+ const outcomes = await Promise.all(relays.map(async (relay) => {
289
+ if (!this.#opts.prune || signature === null) {
290
+ // No seam wired, or no key to sign with, is not a successful prune. Say which it was.
291
+ return { relay, ok: false, reason: signature === null ? "key_unavailable" : "relay_prune_unavailable" };
292
+ }
293
+ try {
294
+ const answer = await this.#opts.prune(relay, { channelHex, throughSeq, timeMs, signature });
295
+ if (!answer.ok) {
296
+ logger.warn("channel.prune.relay_refused", {
297
+ ...(correlationId !== undefined ? { correlationId } : {}),
298
+ channel_pubkey: channelHex, relay, through_seq: throughSeq, reason: answer.reason,
299
+ });
300
+ return { relay, ok: false, reason: answer.reason };
301
+ }
302
+ return { relay, ok: true };
303
+ }
304
+ catch (err) {
305
+ logger.warn("channel.prune.relay_unreachable", {
306
+ ...(correlationId !== undefined ? { correlationId } : {}),
307
+ channel_pubkey: channelHex, relay, through_seq: throughSeq, reason: extract(err),
308
+ });
309
+ return { relay, ok: false, reason: extract(err) };
310
+ }
311
+ }));
312
+ logger.info("channel.log.pruned", {
313
+ ...(correlationId !== undefined ? { correlationId } : {}),
314
+ agent: agentName,
315
+ channel_pubkey: channelHex, through_seq: throughSeq, pruned,
316
+ relays_pruned: outcomes.filter((o) => o.ok).map((o) => o.relay),
317
+ relays_still_holding: outcomes.filter((o) => !o.ok).map((o) => o.relay),
318
+ });
319
+ return { pruned, relays: outcomes };
320
+ }
321
+ /**
322
+ * Sign and deposit the channel's info record. Only the CHANNEL key signs it.
323
+ *
324
+ * ⚠️ **THE DEPOSIT IS THE POINT, NOT THE SIGNATURE.** The record is the only way a subscriber
325
+ * learns a channel's relays, access and admin key. This used to sign it, log
326
+ * `channel.info.published` and return the bytes to the caller without contacting a relay — so an
327
+ * operator was told their channel was published while no one could find it. The event now names
328
+ * only the relays that actually took it.
329
+ */
330
+ async publishInfo(agentName, channelHex, correlationId) {
331
+ const { logger } = this.#opts;
332
+ const info = this.#opts.channelInfo(channelHex);
333
+ const channelKey = this.#opts.getChannelKey(channelHex);
334
+ const agentKey = this.#opts.getAgentKey(agentName);
335
+ if (!info)
336
+ return { ok: false, reason: "channel_unknown" };
337
+ if (!channelKey || !agentKey)
338
+ return { ok: false, reason: "key_unavailable" };
339
+ const record = await signChannelInfo(channelKey, {
340
+ access: info.access,
341
+ admin_pubkey: await agentKey.getPublicKey(),
342
+ relays: info.relays,
343
+ guidance: info.guidance,
344
+ retention_seconds: info.retention_seconds,
345
+ updated_at: this.#now(),
346
+ ext: null,
347
+ });
348
+ const info_cbor = encodeChannelInfo(record);
349
+ const outcomes = await Promise.all(info.relays.map(async (relay) => {
350
+ try {
351
+ const answer = await this.#opts.depositInfo(relay, { info_cbor });
352
+ if (!answer.ok)
353
+ return { relay, ok: false, reason: answer.reason };
354
+ return { relay, ok: true };
355
+ }
356
+ catch (err) {
357
+ return { relay, ok: false, reason: extract(err) };
358
+ }
359
+ }));
360
+ const took = outcomes.filter((o) => o.ok);
361
+ if (took.length === 0) {
362
+ logger.warn("channel.info.deposit_failed", {
363
+ ...(correlationId !== undefined ? { correlationId } : {}),
364
+ channel_pubkey: channelHex,
365
+ reasons: outcomes.map((o) => o.reason ?? "unknown"),
366
+ });
367
+ return { ok: false, reason: "no_relay_accepted", detail: outcomes.map((o) => `${o.relay}: ${o.reason ?? "unknown"}`).join("; ") };
368
+ }
369
+ logger.info("channel.info.published", {
370
+ ...(correlationId !== undefined ? { correlationId } : {}),
371
+ channel_pubkey: channelHex, access: info.access,
372
+ relays_ok: took.map((o) => o.relay),
373
+ relays_failed: outcomes.filter((o) => !o.ok).map((o) => o.relay),
374
+ });
375
+ return { ok: true, info_cbor, relays: outcomes };
376
+ }
377
+ /** The relays this channel publishes to, so a caller can refill all of them without naming one. */
378
+ relaysFor(channelHex) {
379
+ return this.#opts.channelInfo(channelHex)?.relays ?? [];
380
+ }
381
+ /** The pacing gap between refill deposits. Its own method so a test can drive it to zero. */
382
+ #pause(ms) {
383
+ if (ms <= 0)
384
+ return Promise.resolve();
385
+ return new Promise((resolve) => { setTimeout(resolve, ms); });
386
+ }
387
+ }
388
+ function extract(err) {
389
+ if (err instanceof Error)
390
+ return err.message;
391
+ const m = err?.message;
392
+ return typeof m === "string" ? m : JSON.stringify(err);
393
+ }
394
+ //# sourceMappingURL=channel-publisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-publisher.js","sourceRoot":"","sources":["../src/channel-publisher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import type { CelloNode } from "@cello-protocol/transport";
2
+ import type { Logger } from "./types.js";
3
+ export declare const CHANNEL_PROTOCOL_ID = "/cello/channel/1.0.0";
4
+ export interface ChannelRelayClientOptions {
5
+ getNode: () => CelloNode | null;
6
+ logger: Logger;
7
+ }
8
+ export declare class ChannelRelayClient {
9
+ #private;
10
+ constructor(opts: ChannelRelayClientOptions);
11
+ /**
12
+ * One request, one stream. THROWS when the relay could not be reached at all, and RESOLVES with
13
+ * whatever the relay said otherwise — including a refusal, which is an answer.
14
+ */
15
+ request(relayAddr: string, frame: Record<string, unknown>): Promise<Record<string, unknown>>;
16
+ /** Deposit one post. A refusal comes back as `{ ok: false, reason }`, never as a throw. */
17
+ deposit(relayAddr: string, req: {
18
+ post_cbor: Uint8Array;
19
+ fetch_key?: {
20
+ pubkey: Uint8Array;
21
+ time_ms: number;
22
+ signature: Uint8Array;
23
+ };
24
+ }): Promise<{
25
+ ok: true;
26
+ receipt_cbor: Uint8Array;
27
+ } | {
28
+ ok: false;
29
+ reason: string;
30
+ skew_ms?: number;
31
+ }>;
32
+ /** Fetch from a post number. The caller verifies everything that comes back. */
33
+ fetch(relayAddr: string, req: {
34
+ channel_pubkey: Uint8Array;
35
+ since_seq: number;
36
+ max_bytes: number;
37
+ auth?: {
38
+ signature: Uint8Array;
39
+ time_ms: number;
40
+ };
41
+ agent_pubkeys?: Uint8Array[];
42
+ }): Promise<{
43
+ ok: true;
44
+ posts: Array<{
45
+ seq: number;
46
+ post_cbor: Uint8Array;
47
+ receipt_cbor?: Uint8Array;
48
+ }>;
49
+ first_held_seq: number | null;
50
+ last_seq: number | null;
51
+ } | {
52
+ ok: false;
53
+ reason: string;
54
+ }>;
55
+ /** Where a relay's queue begins and ends, without pulling any posts. */
56
+ head(relayAddr: string, channelPubkey: Uint8Array): Promise<{
57
+ first_held_seq: number | null;
58
+ last_seq: number | null;
59
+ }>;
60
+ /**
61
+ * Deposit the channel's info record. No receipt: the record carries no post number, so there is
62
+ * nothing for a relay to order or countersign — it either holds the latest one or it does not.
63
+ */
64
+ depositInfo(relayAddr: string, req: {
65
+ info_cbor: Uint8Array;
66
+ }): Promise<{
67
+ ok: true;
68
+ } | {
69
+ ok: false;
70
+ reason: string;
71
+ }>;
72
+ /** Ask a relay to drop everything through a post number. Oldest end only — the relay enforces that. */
73
+ prune(relayAddr: string, req: {
74
+ channel_pubkey: Uint8Array;
75
+ through_seq: number;
76
+ time_ms: number;
77
+ signature: Uint8Array;
78
+ }): Promise<{
79
+ ok: true;
80
+ dropped?: number;
81
+ } | {
82
+ ok: false;
83
+ reason: string;
84
+ }>;
85
+ /** The channel's info record as this relay holds it, or null. */
86
+ info(relayAddr: string, channelPubkey: Uint8Array): Promise<Uint8Array | null>;
87
+ }
88
+ //# sourceMappingURL=channel-relay-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-relay-client.d.ts","sourceRoot":"","sources":["../src/channel-relay-client.ts"],"names":[],"mappings":"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"}