@cello-protocol/transport 0.0.4 → 0.0.5

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.
@@ -0,0 +1,85 @@
1
+ /**
2
+ * CELLO Transport — autonat-service.ts (CELLO-M7-TRANSPORT-001)
3
+ *
4
+ * NodeAutoNatService — the REAL IAutoNatService adapter (CELLO_ENV dev/staging/
5
+ * production). It wraps a started CelloNode and surfaces the node's
6
+ * libp2p-AutoNAT-driven dialability observable, gated by the directory-node prober
7
+ * set, and emits the story's AutoNAT observability events through an injected
8
+ * Logger.
9
+ *
10
+ * ─── Why this exists (review finding C2 + C1) ────────────────────────────────
11
+ * The transport node owns a dialability observable but emits NO log events. The
12
+ * story REQUIRES:
13
+ * - transport.autonat.result (INFO, every probe cycle) — { dialable,
14
+ * publicAddr, nodeType }
15
+ * - transport.autonat.unavailable (WARN, when no directory probers are
16
+ * reachable) — { nodeType,
17
+ * directorySignalingStatus }
18
+ * NodeAutoNatService is where those events are produced. It is the production
19
+ * counterpart of LocalAutoNatStub (which returns canned values with no node).
20
+ *
21
+ * ─── SI-002: probers are exclusively manifest directory nodes ────────────────
22
+ * AutoNAT can only run when at least one manifest-verified directory node is
23
+ * connected to act as a dial-back prober. When the prober set is empty (directory
24
+ * in 'reconnecting' state — SIGNAL-001), AutoNAT cannot run: getDialability()
25
+ * returns the conservative DEFAULT_DIALABILITY ({ dialable:false, publicAddr:null })
26
+ * regardless of what the node's raw observable says, and the dual unavailable
27
+ * WARN event fires. A rogue non-manifest responder is never in the prober set, so
28
+ * it can never push the node to dialable:true.
29
+ */
30
+ import type { CelloNode } from "./types.js";
31
+ import type { Dialability, IAutoNatService, Unsubscribe } from "./autonat.js";
32
+ /** Minimal logger surface used by NodeAutoNatService (injected, never imported). */
33
+ export interface AutoNatLogger {
34
+ info(event: string, context: Record<string, unknown>): void;
35
+ warn(event: string, context: Record<string, unknown>): void;
36
+ }
37
+ export type AutoNatNodeType = "session" | "standing_receiver";
38
+ export interface NodeAutoNatServiceOptions {
39
+ /** The started CelloNode whose AutoNAT dialability this service surfaces. */
40
+ node: CelloNode;
41
+ /** Injected logger for the AutoNAT observability events. */
42
+ logger: AutoNatLogger;
43
+ /** 'standing_receiver' or 'session' — recorded on every event. */
44
+ nodeType: AutoNatNodeType;
45
+ /**
46
+ * Directory-node multiaddrs serving as AutoNAT probers (SI-002). Empty when the
47
+ * directory connection is in 'reconnecting' state — AutoNAT cannot run then.
48
+ */
49
+ probers?: string[];
50
+ /**
51
+ * Source of the directory signaling status string for the unavailable event.
52
+ * Defaults to 'reconnecting' (the only state in which probers are empty).
53
+ */
54
+ directorySignalingStatus?: () => string;
55
+ }
56
+ /**
57
+ * Real IAutoNatService over a live CelloNode. Subscribes to the node's dialability
58
+ * observable; every change emits transport.autonat.result (and, when no probers
59
+ * are reachable, transport.autonat.unavailable).
60
+ */
61
+ export declare class NodeAutoNatService implements IAutoNatService {
62
+ #private;
63
+ constructor(opts: NodeAutoNatServiceOptions);
64
+ /**
65
+ * Current dialability. AutoNAT requires at least one directory-node prober; when
66
+ * the prober set is empty (reconnecting), return the conservative default — the
67
+ * node's raw observable is not trusted because no manifest prober confirmed it
68
+ * (SI-002 / AC-004 / DB-001).
69
+ */
70
+ getDialability(): Dialability;
71
+ /** The manifest directory-node prober set (SI-002). */
72
+ getProbers(): string[];
73
+ onChange(listener: (d: Dialability) => void): Unsubscribe;
74
+ /** Update the prober set (e.g. on directory connect/disconnect). */
75
+ setProbers(probers: string[]): void;
76
+ /**
77
+ * Emit the current probe result. Call once after the node has started so the
78
+ * standing-receiver/session node's initial dialability (and any unavailable
79
+ * condition) is logged even before libp2p fires its first self:peer:update.
80
+ */
81
+ emitInitialResult(): void;
82
+ /** Release the node subscription. */
83
+ stop(): void;
84
+ }
85
+ //# sourceMappingURL=autonat-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonat-service.d.ts","sourceRoot":"","sources":["../src/autonat-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9E,oFAAoF;AACpF,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7D;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,mBAAmB,CAAC;AAE9D,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,IAAI,EAAE,SAAS,CAAC;IAChB,4DAA4D;IAC5D,MAAM,EAAE,aAAa,CAAC;IACtB,kEAAkE;IAClE,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,wBAAwB,CAAC,EAAE,MAAM,MAAM,CAAC;CACzC;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,eAAe;;gBAS5C,IAAI,EAAE,yBAAyB;IAW3C;;;;;OAKG;IACH,cAAc,IAAI,WAAW;IAK7B,uDAAuD;IACvD,UAAU,IAAI,MAAM,EAAE;IAItB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW;IAOzD,oEAAoE;IACpE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAInC;;;;OAIG;IACH,iBAAiB,IAAI,IAAI;IAIzB,qCAAqC;IACrC,IAAI,IAAI,IAAI;CA+Bb"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * CELLO Transport — autonat-service.ts (CELLO-M7-TRANSPORT-001)
3
+ *
4
+ * NodeAutoNatService — the REAL IAutoNatService adapter (CELLO_ENV dev/staging/
5
+ * production). It wraps a started CelloNode and surfaces the node's
6
+ * libp2p-AutoNAT-driven dialability observable, gated by the directory-node prober
7
+ * set, and emits the story's AutoNAT observability events through an injected
8
+ * Logger.
9
+ *
10
+ * ─── Why this exists (review finding C2 + C1) ────────────────────────────────
11
+ * The transport node owns a dialability observable but emits NO log events. The
12
+ * story REQUIRES:
13
+ * - transport.autonat.result (INFO, every probe cycle) — { dialable,
14
+ * publicAddr, nodeType }
15
+ * - transport.autonat.unavailable (WARN, when no directory probers are
16
+ * reachable) — { nodeType,
17
+ * directorySignalingStatus }
18
+ * NodeAutoNatService is where those events are produced. It is the production
19
+ * counterpart of LocalAutoNatStub (which returns canned values with no node).
20
+ *
21
+ * ─── SI-002: probers are exclusively manifest directory nodes ────────────────
22
+ * AutoNAT can only run when at least one manifest-verified directory node is
23
+ * connected to act as a dial-back prober. When the prober set is empty (directory
24
+ * in 'reconnecting' state — SIGNAL-001), AutoNAT cannot run: getDialability()
25
+ * returns the conservative DEFAULT_DIALABILITY ({ dialable:false, publicAddr:null })
26
+ * regardless of what the node's raw observable says, and the dual unavailable
27
+ * WARN event fires. A rogue non-manifest responder is never in the prober set, so
28
+ * it can never push the node to dialable:true.
29
+ */
30
+ import { DEFAULT_DIALABILITY } from "./autonat.js";
31
+ /**
32
+ * Real IAutoNatService over a live CelloNode. Subscribes to the node's dialability
33
+ * observable; every change emits transport.autonat.result (and, when no probers
34
+ * are reachable, transport.autonat.unavailable).
35
+ */
36
+ export class NodeAutoNatService {
37
+ #node;
38
+ #logger;
39
+ #nodeType;
40
+ #probers;
41
+ #getStatus;
42
+ #listeners = new Set();
43
+ #unsubNode;
44
+ constructor(opts) {
45
+ this.#node = opts.node;
46
+ this.#logger = opts.logger;
47
+ this.#nodeType = opts.nodeType;
48
+ this.#probers = opts.probers ? [...opts.probers] : [];
49
+ this.#getStatus = opts.directorySignalingStatus ?? (() => "reconnecting");
50
+ // Each AutoNAT probe cycle that changes the node's dialability re-emits the
51
+ // result event and notifies daemon-side observers.
52
+ this.#unsubNode = this.#node.onDialabilityChange((d) => this.#emitResult(d));
53
+ }
54
+ /**
55
+ * Current dialability. AutoNAT requires at least one directory-node prober; when
56
+ * the prober set is empty (reconnecting), return the conservative default — the
57
+ * node's raw observable is not trusted because no manifest prober confirmed it
58
+ * (SI-002 / AC-004 / DB-001).
59
+ */
60
+ getDialability() {
61
+ if (this.#probers.length === 0)
62
+ return { ...DEFAULT_DIALABILITY };
63
+ return this.#node.getDialability();
64
+ }
65
+ /** The manifest directory-node prober set (SI-002). */
66
+ getProbers() {
67
+ return [...this.#probers];
68
+ }
69
+ onChange(listener) {
70
+ this.#listeners.add(listener);
71
+ return () => {
72
+ this.#listeners.delete(listener);
73
+ };
74
+ }
75
+ /** Update the prober set (e.g. on directory connect/disconnect). */
76
+ setProbers(probers) {
77
+ this.#probers = [...probers];
78
+ }
79
+ /**
80
+ * Emit the current probe result. Call once after the node has started so the
81
+ * standing-receiver/session node's initial dialability (and any unavailable
82
+ * condition) is logged even before libp2p fires its first self:peer:update.
83
+ */
84
+ emitInitialResult() {
85
+ this.#emitResult(this.#node.getDialability());
86
+ }
87
+ /** Release the node subscription. */
88
+ stop() {
89
+ this.#unsubNode();
90
+ }
91
+ #emitResult(raw) {
92
+ const noProbers = this.#probers.length === 0;
93
+ // When AutoNAT cannot run, force the conservative default — the node's raw
94
+ // observable was never confirmed by a manifest prober (SI-002).
95
+ const d = noProbers ? { ...DEFAULT_DIALABILITY } : raw;
96
+ this.#logger.info("transport.autonat.result", {
97
+ dialable: d.dialable,
98
+ publicAddr: d.publicAddr,
99
+ nodeType: this.#nodeType,
100
+ ...(noProbers
101
+ ? { note: "autonat_unavailable — directory in reconnecting state" }
102
+ : {}),
103
+ });
104
+ // Dual-event (story Observability §notes): the unavailable WARN fires
105
+ // alongside the INFO result whenever AutoNAT could not run. The INFO event is
106
+ // the standard per-probe report; the WARN drives operational alarms.
107
+ if (noProbers) {
108
+ this.#logger.warn("transport.autonat.unavailable", {
109
+ nodeType: this.#nodeType,
110
+ directorySignalingStatus: this.#getStatus(),
111
+ });
112
+ }
113
+ for (const l of this.#listeners)
114
+ l({ ...d });
115
+ }
116
+ }
117
+ //# sourceMappingURL=autonat-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonat-service.js","sourceRoot":"","sources":["../src/autonat-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * CELLO Transport — autonat.ts (CELLO-M7-TRANSPORT-001)
3
+ *
4
+ * AutoNAT dialability detection for session and standing-receiver nodes.
5
+ *
6
+ * ─── Specification (Phase S) ──────────────────────────────────────────────────
7
+ * AutoNAT (libp2p) asks already-connected peers to dial back the node's
8
+ * advertised address. If a dial-back succeeds, the node is publicly dialable; if
9
+ * it fails, the node is behind NAT and must use a relay circuit address. CELLO
10
+ * uses directory nodes (manifest-verified, three independent regions) as the
11
+ * dial-back probers — they are already connected and trusted, so no dedicated
12
+ * AutoNAT bootstrap infrastructure is required.
13
+ *
14
+ * Adapter pattern (mandatory per CLAUDE.md):
15
+ * IAutoNatService is the daemon-facing adapter for querying dialability. The
16
+ * real implementation (NodeAutoNatService) wraps a CelloNode and surfaces the
17
+ * node's libp2p-driven dialability observable, plus the directory prober set
18
+ * obtained from the daemon context. LocalAutoNatStub returns configurable
19
+ * values without any network access (CELLO_ENV='local'|'test').
20
+ *
21
+ * SI-002: probers are exclusively directory nodes whose identity is verified via
22
+ * the consortium manifest. libp2p AutoNAT v1 probes connected peers; CELLO only
23
+ * connects to manifest-verified directory nodes (enforced by the connection
24
+ * policy / connection gater), so the effective prober set is the directory node
25
+ * set. getProbers() surfaces that set so callers can assert it (AC-001(c)) and so
26
+ * a rogue non-manifest responder cannot be counted (SI-002).
27
+ *
28
+ * ─── Pseudocode (Phase P) ─────────────────────────────────────────────────────
29
+ * Dialability is { dialable, publicAddr }:
30
+ * - dialable: true iff AutoNAT confirmed at least one externally-reachable
31
+ * (public, non-circuit) multiaddr.
32
+ * - publicAddr: that confirmed multiaddr, or null when behind NAT / undetermined.
33
+ *
34
+ * LocalAutoNatStub:
35
+ * constructor(initial = { dialable: false, publicAddr: null }, probers = [])
36
+ * getDialability(): return current
37
+ * getProbers(): return probers
38
+ * onChange(cb): register; return unsubscribe
39
+ * setDialability(next): set current; notify all listeners (test driver)
40
+ * setProbers(p): set probers (test driver — e.g. simulate reconnecting => [])
41
+ */
42
+ /**
43
+ * The result of an AutoNAT probe cycle. Node-level (not session-scoped).
44
+ * dialable — true if at least one directory node confirmed dial-back success.
45
+ * publicAddr — the externally-reachable multiaddr if dialable; null otherwise.
46
+ */
47
+ export interface Dialability {
48
+ dialable: boolean;
49
+ publicAddr: string | null;
50
+ }
51
+ /** Conservative default used before any probe completes / when AutoNAT cannot run. */
52
+ export declare const DEFAULT_DIALABILITY: Dialability;
53
+ /** Unsubscribe handle returned by observe registrations. */
54
+ export type Unsubscribe = () => void;
55
+ /**
56
+ * Daemon-facing adapter for dialability. The session establishment logic reads
57
+ * getDialability() to decide what address to advertise in the SessionAssignment
58
+ * negotiation (direct multiaddr when dialable, relay circuit address otherwise).
59
+ */
60
+ export interface IAutoNatService {
61
+ /** Current dialability. Returns DEFAULT_DIALABILITY before the first probe. */
62
+ getDialability(): Dialability;
63
+ /**
64
+ * The directory-node multiaddrs serving as AutoNAT probers (SI-002). Empty when
65
+ * no directory nodes are connected (reconnecting state — AutoNAT cannot run).
66
+ */
67
+ getProbers(): string[];
68
+ /** Observe dialability changes. Returns an unsubscribe handle. */
69
+ onChange(listener: (d: Dialability) => void): Unsubscribe;
70
+ }
71
+ /**
72
+ * In-process AutoNAT stub. Returns configurable dialability with no network
73
+ * access. Selected when CELLO_ENV is 'local' or 'test'. Defaults to NOT dialable
74
+ * (the conservative relay fallback) per the story's edge-case requirements.
75
+ */
76
+ export declare class LocalAutoNatStub implements IAutoNatService {
77
+ #private;
78
+ constructor(opts?: {
79
+ dialability?: Dialability;
80
+ probers?: string[];
81
+ });
82
+ getDialability(): Dialability;
83
+ getProbers(): string[];
84
+ onChange(listener: (d: Dialability) => void): Unsubscribe;
85
+ /** Test driver: update dialability and notify observers. */
86
+ setDialability(next: Dialability): void;
87
+ /** Test driver: set the prober set (e.g. [] to simulate the reconnecting state). */
88
+ setProbers(probers: string[]): void;
89
+ }
90
+ //# sourceMappingURL=autonat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonat.d.ts","sourceRoot":"","sources":["../src/autonat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAIH;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,EAAE,WAGhC,CAAC;AAEH,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAIrC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,cAAc,IAAI,WAAW,CAAC;IAC9B;;;OAGG;IACH,UAAU,IAAI,MAAM,EAAE,CAAC;IACvB,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW,CAAC;CAC3D;AAID;;;;GAIG;AACH,qBAAa,gBAAiB,YAAW,eAAe;;gBAK1C,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,WAAW,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE;IAKpE,cAAc,IAAI,WAAW;IAI7B,UAAU,IAAI,MAAM,EAAE;IAItB,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,GAAG,WAAW;IAOzD,4DAA4D;IAC5D,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAKvC,oFAAoF;IACpF,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;CAGpC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * CELLO Transport — autonat.ts (CELLO-M7-TRANSPORT-001)
3
+ *
4
+ * AutoNAT dialability detection for session and standing-receiver nodes.
5
+ *
6
+ * ─── Specification (Phase S) ──────────────────────────────────────────────────
7
+ * AutoNAT (libp2p) asks already-connected peers to dial back the node's
8
+ * advertised address. If a dial-back succeeds, the node is publicly dialable; if
9
+ * it fails, the node is behind NAT and must use a relay circuit address. CELLO
10
+ * uses directory nodes (manifest-verified, three independent regions) as the
11
+ * dial-back probers — they are already connected and trusted, so no dedicated
12
+ * AutoNAT bootstrap infrastructure is required.
13
+ *
14
+ * Adapter pattern (mandatory per CLAUDE.md):
15
+ * IAutoNatService is the daemon-facing adapter for querying dialability. The
16
+ * real implementation (NodeAutoNatService) wraps a CelloNode and surfaces the
17
+ * node's libp2p-driven dialability observable, plus the directory prober set
18
+ * obtained from the daemon context. LocalAutoNatStub returns configurable
19
+ * values without any network access (CELLO_ENV='local'|'test').
20
+ *
21
+ * SI-002: probers are exclusively directory nodes whose identity is verified via
22
+ * the consortium manifest. libp2p AutoNAT v1 probes connected peers; CELLO only
23
+ * connects to manifest-verified directory nodes (enforced by the connection
24
+ * policy / connection gater), so the effective prober set is the directory node
25
+ * set. getProbers() surfaces that set so callers can assert it (AC-001(c)) and so
26
+ * a rogue non-manifest responder cannot be counted (SI-002).
27
+ *
28
+ * ─── Pseudocode (Phase P) ─────────────────────────────────────────────────────
29
+ * Dialability is { dialable, publicAddr }:
30
+ * - dialable: true iff AutoNAT confirmed at least one externally-reachable
31
+ * (public, non-circuit) multiaddr.
32
+ * - publicAddr: that confirmed multiaddr, or null when behind NAT / undetermined.
33
+ *
34
+ * LocalAutoNatStub:
35
+ * constructor(initial = { dialable: false, publicAddr: null }, probers = [])
36
+ * getDialability(): return current
37
+ * getProbers(): return probers
38
+ * onChange(cb): register; return unsubscribe
39
+ * setDialability(next): set current; notify all listeners (test driver)
40
+ * setProbers(p): set probers (test driver — e.g. simulate reconnecting => [])
41
+ */
42
+ /** Conservative default used before any probe completes / when AutoNAT cannot run. */
43
+ export const DEFAULT_DIALABILITY = Object.freeze({
44
+ dialable: false,
45
+ publicAddr: null,
46
+ });
47
+ // ─── LocalAutoNatStub ─────────────────────────────────────────────────────────
48
+ /**
49
+ * In-process AutoNAT stub. Returns configurable dialability with no network
50
+ * access. Selected when CELLO_ENV is 'local' or 'test'. Defaults to NOT dialable
51
+ * (the conservative relay fallback) per the story's edge-case requirements.
52
+ */
53
+ export class LocalAutoNatStub {
54
+ #dialability;
55
+ #probers;
56
+ #listeners = new Set();
57
+ constructor(opts) {
58
+ this.#dialability = opts?.dialability ?? { ...DEFAULT_DIALABILITY };
59
+ this.#probers = opts?.probers ? [...opts.probers] : [];
60
+ }
61
+ getDialability() {
62
+ return { ...this.#dialability };
63
+ }
64
+ getProbers() {
65
+ return [...this.#probers];
66
+ }
67
+ onChange(listener) {
68
+ this.#listeners.add(listener);
69
+ return () => {
70
+ this.#listeners.delete(listener);
71
+ };
72
+ }
73
+ /** Test driver: update dialability and notify observers. */
74
+ setDialability(next) {
75
+ this.#dialability = { ...next };
76
+ for (const l of this.#listeners)
77
+ l(this.getDialability());
78
+ }
79
+ /** Test driver: set the prober set (e.g. [] to simulate the reconnecting state). */
80
+ setProbers(probers) {
81
+ this.#probers = [...probers];
82
+ }
83
+ }
84
+ //# sourceMappingURL=autonat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autonat.js","sourceRoot":"","sources":["../src/autonat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAcH,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAgB,MAAM,CAAC,MAAM,CAAC;IAC5D,QAAQ,EAAE,KAAK;IACf,UAAU,EAAE,IAAI;CACjB,CAAC,CAAC;AAwBH,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAC3B,YAAY,CAAc;IAC1B,QAAQ,CAAW;IACV,UAAU,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE1D,YAAY,IAAwD;QAClE,IAAI,CAAC,YAAY,GAAG,IAAI,EAAE,WAAW,IAAI,EAAE,GAAG,mBAAmB,EAAE,CAAC;QACpE,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,CAAC;IAED,cAAc;QACZ,OAAO,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IAClC,CAAC;IAED,UAAU;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAED,QAAQ,CAAC,QAAkC;QACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC,CAAC;IACJ,CAAC;IAED,4DAA4D;IAC5D,cAAc,CAAC,IAAiB;QAC9B,IAAI,CAAC,YAAY,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU;YAAE,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,oFAAoF;IACpF,UAAU,CAAC,OAAiB;QAC1B,IAAI,CAAC,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * CELLO-M7-MSG-001 — transport content-size cap.
3
+ *
4
+ * Reads the first length-prefixed frame from a content stream and enforces the
5
+ * application content cap (MAX_CONTENT_BYTES = 1 MB) EXPLICITLY, before the bare
6
+ * it-length-prefixed transport default (4 MB) can fire. Oversize content yields a
7
+ * distinct `content_too_large` outcome — never a silent decode failure that the
8
+ * caller mistakes for a desync (AC-014, SI-003).
9
+ *
10
+ * Pseudocode (SPARC Phase P):
11
+ * readCappedContentFrame(source, cap):
12
+ * decode with maxDataLength = transport default (4 MB) so 1–4 MB frames are
13
+ * observable and we can report their exact size
14
+ * for first frame:
15
+ * payload = bytes
16
+ * if payload.length > cap → { ok:false, content_too_large, size, cap }
17
+ * else → { ok:true, payload }
18
+ * no frame → { ok:false, empty }
19
+ * decode throw (e.g. > 4 MB transport max) → { ok:false, content_too_large }
20
+ */
21
+ export type CappedFrameResult = {
22
+ ok: true;
23
+ payload: Uint8Array;
24
+ } | {
25
+ ok: false;
26
+ reason: "content_too_large";
27
+ size?: number;
28
+ cap: number;
29
+ message?: string;
30
+ } | {
31
+ ok: false;
32
+ reason: "empty";
33
+ } | {
34
+ ok: false;
35
+ reason: "decode_error";
36
+ message: string;
37
+ };
38
+ /**
39
+ * Read and length-cap the first content frame off a length-prefixed source.
40
+ * `cap` defaults to the 1 MB application message cap.
41
+ */
42
+ export declare function readCappedContentFrame(source: AsyncIterable<Uint8Array>, cap?: number): Promise<CappedFrameResult>;
43
+ //# sourceMappingURL=content-cap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-cap.d.ts","sourceRoot":"","sources":["../src/content-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAC9B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAU3D;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,aAAa,CAAC,UAAU,CAAC,EACjC,GAAG,GAAE,MAA0B,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CAoB5B"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * CELLO-M7-MSG-001 — transport content-size cap.
3
+ *
4
+ * Reads the first length-prefixed frame from a content stream and enforces the
5
+ * application content cap (MAX_CONTENT_BYTES = 1 MB) EXPLICITLY, before the bare
6
+ * it-length-prefixed transport default (4 MB) can fire. Oversize content yields a
7
+ * distinct `content_too_large` outcome — never a silent decode failure that the
8
+ * caller mistakes for a desync (AC-014, SI-003).
9
+ *
10
+ * Pseudocode (SPARC Phase P):
11
+ * readCappedContentFrame(source, cap):
12
+ * decode with maxDataLength = transport default (4 MB) so 1–4 MB frames are
13
+ * observable and we can report their exact size
14
+ * for first frame:
15
+ * payload = bytes
16
+ * if payload.length > cap → { ok:false, content_too_large, size, cap }
17
+ * else → { ok:true, payload }
18
+ * no frame → { ok:false, empty }
19
+ * decode throw (e.g. > 4 MB transport max) → { ok:false, content_too_large }
20
+ */
21
+ import * as lp from "it-length-prefixed";
22
+ import { MAX_CONTENT_BYTES, IT_LENGTH_PREFIX_DEFAULT_MAX } from "@cello-protocol/protocol-types";
23
+ function toU8(chunk) {
24
+ if (chunk instanceof Uint8Array)
25
+ return chunk;
26
+ // Uint8ArrayList from it-length-prefixed exposes subarray()
27
+ const c = chunk;
28
+ if (typeof c?.subarray === "function")
29
+ return c.subarray();
30
+ return new Uint8Array(chunk);
31
+ }
32
+ /**
33
+ * Read and length-cap the first content frame off a length-prefixed source.
34
+ * `cap` defaults to the 1 MB application message cap.
35
+ */
36
+ export async function readCappedContentFrame(source, cap = MAX_CONTENT_BYTES) {
37
+ try {
38
+ for await (const chunk of lp.decode(source, { maxDataLength: IT_LENGTH_PREFIX_DEFAULT_MAX })) {
39
+ const payload = toU8(chunk);
40
+ if (payload.length > cap) {
41
+ return { ok: false, reason: "content_too_large", size: payload.length, cap };
42
+ }
43
+ return { ok: true, payload };
44
+ }
45
+ return { ok: false, reason: "empty" };
46
+ }
47
+ catch (err) {
48
+ const message = err instanceof Error ? err.message : String(err);
49
+ // A frame larger than the it-length-prefixed transport default trips the
50
+ // decoder's max-length guard. Surface it as content_too_large (never a silent
51
+ // failure, never a desync) rather than an opaque decode error.
52
+ if (/max|length|too long|data length/i.test(message)) {
53
+ return { ok: false, reason: "content_too_large", cap, message };
54
+ }
55
+ return { ok: false, reason: "decode_error", message };
56
+ }
57
+ }
58
+ //# sourceMappingURL=content-cap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-cap.js","sourceRoot":"","sources":["../src/content-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAQjG,SAAS,IAAI,CAAC,KAAc;IAC1B,IAAI,KAAK,YAAY,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9C,4DAA4D;IAC5D,MAAM,CAAC,GAAG,KAAwC,CAAC;IACnD,IAAI,OAAO,CAAC,EAAE,QAAQ,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC3D,OAAO,IAAI,UAAU,CAAC,KAAwB,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAiC,EACjC,MAAc,iBAAiB;IAE/B,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,4BAA4B,EAAE,CAAC,EAAE,CAAC;YAC7F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAgB,CAAC,CAAC;YACvC,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;YAC/E,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACxC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,yEAAyE;QACzE,8EAA8E;QAC9E,+DAA+D;QAC/D,IAAI,kCAAkC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QAClE,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;IACxD,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,5 +6,15 @@
6
6
  export { createNode } from "./node.js";
7
7
  export type { CelloNode, CreateNodeOptions, CelloStreamHandler } from "./types.js";
8
8
  export type { CelloTransportError, ProtocolNotSupportedError, ConnectionLostError, NodeStoppedError, ListenFailedError, } from "./types.js";
9
- export { CELLO_PROTOCOL_ID, CIRCUIT_RELAY_V2_HOP_PROTOCOL_ID, CELLO_CONTENT_PROTOCOL_ID } from "./protocols.js";
9
+ export { CELLO_PROTOCOL_ID, CIRCUIT_RELAY_V2_HOP_PROTOCOL_ID, CELLO_CONTENT_PROTOCOL_ID, AUTONAT_PROTOCOL_ID } from "./protocols.js";
10
+ export type { IAutoNatService, Dialability, Unsubscribe } from "./autonat.js";
11
+ export { LocalAutoNatStub, DEFAULT_DIALABILITY } from "./autonat.js";
12
+ export { NodeAutoNatService } from "./autonat-service.js";
13
+ export type { AutoNatLogger, AutoNatNodeType, NodeAutoNatServiceOptions, } from "./autonat-service.js";
14
+ export { readCappedContentFrame } from "./content-cap.js";
15
+ export type { CappedFrameResult } from "./content-cap.js";
16
+ export type { IManifestVersionStore, IManifestProvider, IDirectoryChallengeVerifier, ChallengeVerifyResult, ChallengeVerifyOk, ChallengeVerifyFail, IManifestPollScheduler, DirectoryKeyProvider, DirectoryManifestStore, } from "./manifest-interfaces.js";
17
+ export { InMemoryManifestVersionStore, TestManifestProvider, TestDirectoryChallengeVerifier, ManifestDirectoryChallengeVerifier, ImmediatePollScheduler, TestDirectoryKeyProvider, TestDirectoryManifestStore, } from "./manifest-stubs.js";
18
+ export { SignalingManager, InMemorySignalingOutboundQueue, buildStep5Tbs, } from "./signaling-manager.js";
19
+ export type { SignalingAuthOkFrame, ManifestPollResponseFrame, ISignalingOutboundQueue, SignalingManagerConfig, SignalingManagerOptions, SignalingLogger, Logger as SignalingConnectionLogger, ProcessStep5Result, SignalingStream, ConnectResult, OperationResult, OperationSuccess, OperationFailure, SignalingFailureReason, } from "./signaling-manager.js";
10
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnF,YAAY,EACV,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACnF,YAAY,EACV,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrI,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EACV,aAAa,EACb,eAAe,EACf,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,2BAA2B,EAC3B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,8BAA8B,EAC9B,kCAAkC,EAClC,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,aAAa,GACd,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,MAAM,IAAI,yBAAyB,EACnC,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,15 @@
4
4
  * Exports the CelloNode factory, interface, protocol constants, and error types.
5
5
  */
6
6
  export { createNode } from "./node.js";
7
- export { CELLO_PROTOCOL_ID, CIRCUIT_RELAY_V2_HOP_PROTOCOL_ID, CELLO_CONTENT_PROTOCOL_ID } from "./protocols.js";
7
+ export { CELLO_PROTOCOL_ID, CIRCUIT_RELAY_V2_HOP_PROTOCOL_ID, CELLO_CONTENT_PROTOCOL_ID, AUTONAT_PROTOCOL_ID } from "./protocols.js";
8
+ export { LocalAutoNatStub, DEFAULT_DIALABILITY } from "./autonat.js";
9
+ // CELLO-M7-TRANSPORT-001: real IAutoNatService over a live CelloNode (emits the
10
+ // transport.autonat.result / transport.autonat.unavailable observability events).
11
+ export { NodeAutoNatService } from "./autonat-service.js";
12
+ // M7-MSG-001: content-size cap on inbound content decode
13
+ export { readCappedContentFrame } from "./content-cap.js";
14
+ // M7-MANIFEST-002: manifest stubs (for test use)
15
+ export { InMemoryManifestVersionStore, TestManifestProvider, TestDirectoryChallengeVerifier, ManifestDirectoryChallengeVerifier, ImmediatePollScheduler, TestDirectoryKeyProvider, TestDirectoryManifestStore, } from "./manifest-stubs.js";
16
+ // M7-SIGNAL-001 + M7-MANIFEST-002: SignalingManager, frame types, and helpers
17
+ export { SignalingManager, InMemorySignalingOutboundQueue, buildStep5Tbs, } from "./signaling-manager.js";
8
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AASvC,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AASvC,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAIrI,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACrE,gFAAgF;AAChF,kFAAkF;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,yDAAyD;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAgB1D,iDAAiD;AACjD,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,8BAA8B,EAC9B,kCAAkC,EAClC,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,8EAA8E;AAC9E,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,aAAa,GACd,MAAM,wBAAwB,CAAC"}