@cosyte/mllp 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { T as Transport } from './index-DAZ4BvJE.cjs';
1
+ import { T as Transport } from './index-CD8V2Mtk.cjs';
2
2
  import { EventEmitter } from 'node:events';
3
3
  import { Socket } from 'node:net';
4
4
  import { TLSSocket } from 'node:tls';
@@ -32,8 +32,8 @@ type WarningCode = "MLLP_MISSING_LEADING_VT" | "MLLP_FS_WITHOUT_CR" | "MLLP_LF_A
32
32
  /**
33
33
  * A frozen warning object emitted when the decoder tolerates a framing deviation.
34
34
  *
35
- * `connectionId` is `undefined` when emitted by a standalone `FrameReader` (Phase 2).
36
- * Phase 3 `Connection` enriches it to the real UUIDv4 before forwarding upstream.
35
+ * `connectionId` is `undefined` when emitted by a standalone `FrameReader`.
36
+ * `Connection` enriches it to the real UUIDv4 before forwarding upstream.
37
37
  *
38
38
  * @example
39
39
  * ```typescript
@@ -52,7 +52,7 @@ interface MllpWarning {
52
52
  readonly byteOffset: number;
53
53
  /**
54
54
  * Connection identifier. `undefined` at the framing layer;
55
- * enriched by Phase 3 `Connection` before emitting upstream.
55
+ * enriched by `Connection` before emitting upstream.
56
56
  */
57
57
  readonly connectionId: string | undefined;
58
58
  /** Wall-clock time at point of emission. */
@@ -62,8 +62,8 @@ interface MllpWarning {
62
62
  * Create a frozen `MllpWarning` object. The returned object is `Object.freeze()`'d
63
63
  * so subscribers cannot mutate shared warning state.
64
64
  *
65
- * `connectionId` is always `undefined` here, Phase 3 enriches via
66
- * `{ ...w, connectionId: this.connectionId }` then re-freezes (D-08).
65
+ * `connectionId` is always `undefined` here; `Connection` enriches it via
66
+ * `{ ...w, connectionId: this.connectionId }` then re-freezes.
67
67
  *
68
68
  * @example
69
69
  * ```typescript
@@ -118,7 +118,7 @@ declare class MllpFramingError extends Error {
118
118
  * This is a **copied** Buffer, isolated from the source buffer so it remains
119
119
  * valid after the underlying buffer is reused or overwritten.
120
120
  *
121
- * **PHI contract (MLLP-9):** the decoder only ever populates this with the single
121
+ * **PHI contract:** the decoder only ever populates this with the single
122
122
  * framing-boundary byte that violated the frame structure (whose hex value the
123
123
  * `message` already discloses), never a run of payload content bytes. For anomalies
124
124
  * whose fault is not a specific byte (`MLLP_FRAME_TOO_LARGE`, the accumulated size),
@@ -180,7 +180,7 @@ interface EncoderOptions {
180
180
  allowDelimiterBytesInPayload?: boolean;
181
181
  /**
182
182
  * Called for each offending delimiter byte when `allowDelimiterBytesInPayload` is `true`.
183
- * Invocation is wrapped in try/catch, a throwing handler does not interrupt encoding (WARN-06).
183
+ * Invocation is wrapped in try/catch, a throwing handler does not interrupt encoding.
184
184
  *
185
185
  * @example
186
186
  * ```typescript
@@ -254,7 +254,7 @@ declare function encodeFrame(payload: Buffer, opts?: EncoderOptions): Buffer;
254
254
  *
255
255
  * All tolerance opts default to `false`, every framing deviation throws unless
256
256
  * explicitly enabled. Server-level defaults (allowFsOnly, allowLfAfterFs, allowLeadingWhitespace)
257
- * are applied by Phase 4 when constructing readers per SERVER-12.
257
+ * are applied by the server when constructing readers.
258
258
  *
259
259
  * @example
260
260
  * ```typescript
@@ -279,27 +279,27 @@ interface FrameReaderOptions {
279
279
  */
280
280
  onFrame: (payload: Buffer, byteOffset: number, warnings: readonly MllpWarning[]) => void;
281
281
  /**
282
- * Called for each tolerated framing deviation. Wrapped in try/catch per WARN-06.
282
+ * Called for each tolerated framing deviation. Wrapped in try/catch.
283
283
  * A throwing handler will not corrupt FSM state.
284
284
  */
285
285
  onWarning?: (w: MllpWarning) => void;
286
286
  /**
287
287
  * Maximum accumulated payload bytes before `MllpFramingError('MLLP_FRAME_TOO_LARGE')`.
288
- * Default: 16 MiB (FRAME-11 DoS prevention).
288
+ * Default: 16 MiB (DoS prevention).
289
289
  */
290
290
  maxFrameSizeBytes?: number;
291
- /** FRAME-07: Tolerate FS without trailing CR; emits `MLLP_FS_WITHOUT_CR`. */
291
+ /** Tolerate FS without trailing CR; emits `MLLP_FS_WITHOUT_CR`. */
292
292
  allowFsOnly?: boolean;
293
- /** FRAME-08: Tolerate FS+LF instead of FS+CR; emits `MLLP_LF_AFTER_FS`. */
293
+ /** Tolerate FS+LF instead of FS+CR; emits `MLLP_LF_AFTER_FS`. */
294
294
  allowLfAfterFs?: boolean;
295
- /** FRAME-09: Tolerate missing leading VT; emits `MLLP_MISSING_LEADING_VT`. */
295
+ /** Tolerate missing leading VT; emits `MLLP_MISSING_LEADING_VT`. */
296
296
  allowMissingLeadingVt?: boolean;
297
- /** FRAME-10: Tolerate SP/TAB/LF/CR before VT; emits `MLLP_LEADING_WHITESPACE`. */
297
+ /** Tolerate SP/TAB/LF/CR before VT; emits `MLLP_LEADING_WHITESPACE`. */
298
298
  allowLeadingWhitespace?: boolean;
299
299
  /**
300
300
  * When `true`, escalates the following tolerances to thrown `MllpFramingError`
301
301
  * even if individual opt-ins (`allowFsOnly`, `allowLfAfterFs`, `allowMissingLeadingVt`,
302
- * `allowLeadingWhitespace`) are enabled (WARN-08):
302
+ * `allowLeadingWhitespace`) are enabled:
303
303
  * - `MLLP_MISSING_LEADING_VT`
304
304
  * - `MLLP_FS_WITHOUT_CR`
305
305
  * - `MLLP_LF_AFTER_FS`
@@ -343,9 +343,9 @@ declare class FrameReader {
343
343
  private _writePos;
344
344
  /** Monotonic absolute stream byte offset across the entire connection lifetime. */
345
345
  private _byteOffset;
346
- /** Byte offset where current leading-whitespace run started (FRAME-10). */
346
+ /** Byte offset where current leading-whitespace run started. */
347
347
  private _wsStart;
348
- /** Count of leading whitespace bytes accumulated in current run (FRAME-10). */
348
+ /** Count of leading whitespace bytes accumulated in current run. */
349
349
  private _wsCount;
350
350
  /** Byte offset of the VT byte that started the current frame. */
351
351
  private _frameStartOffset;
@@ -371,7 +371,7 @@ declare class FrameReader {
371
371
  /**
372
372
  * Clear internal accumulator state and reset byte offset to 0.
373
373
  *
374
- * Call on reconnect / connection reuse to start fresh without allocating a new reader (D-03).
374
+ * Call on reconnect / connection reuse to start fresh without allocating a new reader.
375
375
  * Pending partial frame state is discarded silently.
376
376
  *
377
377
  * @example
@@ -388,10 +388,10 @@ declare class FrameReader {
388
388
  private _appendByte;
389
389
  /**
390
390
  * Copy accumulated payload bytes into a new Buffer and deliver via `onFrame`.
391
- * The copy isolates callers from internal accumulator reuse (T-02-03-03).
391
+ * The copy isolates callers from internal accumulator reuse.
392
392
  */
393
393
  private _deliverFrame;
394
- /** Emit a warning via the `onWarning` callback, swallowing any handler exceptions (WARN-06). */
394
+ /** Emit a warning via the `onWarning` callback, swallowing any handler exceptions. */
395
395
  private _emitWarning;
396
396
  }
397
397
 
@@ -455,7 +455,7 @@ declare class NetTransport implements Transport {
455
455
  }
456
456
 
457
457
  /**
458
- * TlsTransport, `Transport` implementation wrapping a `tls.TLSSocket` (Phase 8).
458
+ * TlsTransport, `Transport` implementation wrapping a `tls.TLSSocket`.
459
459
  *
460
460
  * Identical wiring to `NetTransport` with one deliberate difference: `onConnect`
461
461
  * maps to the socket's `'secureConnect'` event (fires once the TLS handshake
@@ -522,7 +522,7 @@ declare class TlsTransport implements Transport {
522
522
  }
523
523
 
524
524
  /**
525
- * Security-warning codes and payload shape shared by the client and server (Phase 8).
525
+ * Security-warning codes and payload shape shared by the client and server.
526
526
  *
527
527
  * These codes are a **public API**, they appear in `'securityWarning'` event
528
528
  * handlers, log pipelines, and monitoring dashboards. Renaming or removing a
@@ -608,7 +608,7 @@ interface SecurityWarning {
608
608
  }
609
609
 
610
610
  /**
611
- * TLS (MLLPS) option types for the client and server (Phase 8).
611
+ * TLS (MLLPS) option types for the client and server.
612
612
  *
613
613
  * Spec anchor: IHE ATNA, ITI-19 Authenticate Node
614
614
  * (https://profiles.ihe.net/ITI/TF/Volume2/ITI-19.html), the "STX: TLS 1.2
@@ -642,7 +642,7 @@ interface SecurityWarning {
642
642
  */
643
643
  type PemInput = string | Buffer | Array<string | Buffer>;
644
644
  /**
645
- * Client-side TLS options (Phase 8, `ClientOptions.tls`).
645
+ * Client-side TLS options (`ClientOptions.tls`).
646
646
  *
647
647
  * Passing `true` for `ClientOptions.tls` is equivalent to `{}`, TLS enabled
648
648
  * with all defaults, including certificate verification **on**.
@@ -728,7 +728,7 @@ interface TlsOptions {
728
728
  */
729
729
  type ClientAuth = "NONE" | "WANT" | "MUST";
730
730
  /**
731
- * Server-side TLS options (Phase 8, `ServerOptions.tls`).
731
+ * Server-side TLS options (`ServerOptions.tls`).
732
732
  *
733
733
  * @example
734
734
  * ```typescript
@@ -795,9 +795,9 @@ interface ServerTlsOptions {
795
795
  */
796
796
 
797
797
  /**
798
- * The 6 connection states from LIFE-01.
798
+ * The 6 connection states.
799
799
  *
800
- * Transitions are validated against the LIFE-02 edge graph. Illegal transitions
800
+ * Transitions are validated against the legal-transition edge graph. Illegal transitions
801
801
  * are silently ignored to preserve FSM integrity.
802
802
  */
803
803
  type ConnectionState = "CONNECTING" | "CONNECTED" | "DRAINING" | "RECONNECTING" | "DISCONNECTED" | "CLOSED";
@@ -819,8 +819,8 @@ interface StateChangeEvent {
819
819
  /**
820
820
  * Payload for the 'reconnecting' event. Always `Object.freeze`'d.
821
821
  *
822
- * Phase 5 will populate `attempt` and `delayMs` once the reconnect backoff loop
823
- * is implemented. For now only `connectionId` is present at the point of emission.
822
+ * `attempt` and `delayMs` are populated by `MllpClient` when it schedules a
823
+ * reconnect. A `Connection` emitting on its own supplies `connectionId` only.
824
824
  *
825
825
  * @example
826
826
  * ```typescript
@@ -835,7 +835,7 @@ interface ReconnectingEvent {
835
835
  readonly delayMs?: number;
836
836
  }
837
837
  /**
838
- * Return type of `connection.getStats()`, JSON-serializable per OBS-04.
838
+ * Return type of `connection.getStats()`, JSON-serializable.
839
839
  *
840
840
  * All timestamps are `Date | null` (not epoch milliseconds). `JSON.stringify()`
841
841
  * serialises them to ISO 8601 strings by default with no information loss.
@@ -877,9 +877,9 @@ interface ConnectionOptions {
877
877
  transport: Transport;
878
878
  /** Called for each decoded MLLP frame (raw payload bytes, framing stripped). */
879
879
  onMessage?: (payload: Buffer) => void;
880
- /** Per-connection warning subscriber (WARN-10). Replaces previous subscription. */
880
+ /** Per-connection warning subscriber. Replaces previous subscription. */
881
881
  onWarning?: (w: MllpWarning) => void;
882
- /** Drain timeout used by close() in Phase 4/5 (default: 30_000 ms). */
882
+ /** Drain timeout used by close() (default: 30_000 ms). */
883
883
  drainTimeoutMs?: number;
884
884
  /** FrameReader options (tolerance, maxFrameSizeBytes). onFrame/onWarning are managed internally. */
885
885
  framing?: Omit<FrameReaderOptions, "onFrame" | "onWarning">;
@@ -906,7 +906,7 @@ interface ConnectionOptions {
906
906
  * ```
907
907
  */
908
908
  declare class Connection extends EventEmitter {
909
- /** Stable UUIDv4 identifier for this connection (D-11). */
909
+ /** Stable UUIDv4 identifier for this connection. */
910
910
  readonly connectionId: string;
911
911
  private _state;
912
912
  private readonly _transport;
@@ -919,20 +919,19 @@ declare class Connection extends EventEmitter {
919
919
  private _bytesOut;
920
920
  private _lastByteInAt;
921
921
  private _lastByteOutAt;
922
- /** Ring buffer: last MAX_WARNINGS entries (OBS-05). */
922
+ /** Ring buffer: last MAX_WARNINGS entries. */
923
923
  private _warningBuffer;
924
- /** Accurate total counts per code, unaffected by ring buffer truncation (OBS-05). */
924
+ /** Accurate total counts per code, unaffected by ring buffer truncation. */
925
925
  private readonly _warningsByCode;
926
- /** Set to true once the ring buffer overflows (OBS-05). */
926
+ /** Set to true once the ring buffer overflows. */
927
927
  private _warningsTruncated;
928
928
  private _onWarningFn;
929
929
  private _drainPromise;
930
930
  /**
931
931
  * beforeClose hook, no-op default that resolves immediately.
932
932
  *
933
- * Phase 4 (Server) and Phase 5 (Client) override this instance property to
934
- * register ACK-drain and send-queue drain logic respectively (D-07/D-08).
935
- * Connection calls this during `close()`, racing against `drainTimeoutMs`.
933
+ * An owner may replace this instance property to run work before the socket
934
+ * closes. Connection calls it during `close()`, racing against `drainTimeoutMs`.
936
935
  */
937
936
  beforeClose: (drainTimeoutMs: number) => Promise<void>;
938
937
  /**
@@ -943,16 +942,16 @@ declare class Connection extends EventEmitter {
943
942
  */
944
943
  constructor(opts: ConnectionOptions);
945
944
  /**
946
- * Current FSM state. One of the 6 `ConnectionState` values (LIFE-01).
945
+ * Current FSM state. One of the 6 `ConnectionState` values.
947
946
  *
948
947
  * Subscribe to `'stateChange'` events for reactive state monitoring.
949
948
  */
950
949
  get state(): ConnectionState;
951
950
  /**
952
- * Register or replace the per-connection warning subscriber (WARN-10).
951
+ * Register or replace the per-connection warning subscriber.
953
952
  *
954
953
  * Subsequent calls replace the previous handler (set-once semantics prevent leaks).
955
- * The handler is called synchronously and any exception it throws is swallowed (WARN-06).
954
+ * The handler is called synchronously and any exception it throws is swallowed.
956
955
  *
957
956
  * @example
958
957
  * ```typescript
@@ -980,7 +979,7 @@ declare class Connection extends EventEmitter {
980
979
  /**
981
980
  * Write raw bytes to the transport (no framing applied).
982
981
  *
983
- * Phase 4 (Server) and Phase 5 (Client) wrap this with `encodeFrame()` to add MLLP framing.
982
+ * The server and the client wrap this with `encodeFrame()` to add MLLP framing.
984
983
  * Returns `false` if the connection is CLOSED or DISCONNECTED (no bytes written).
985
984
  *
986
985
  * @returns `true` if bytes flushed immediately; `false` if buffered (backpressure) or not writable.
@@ -996,7 +995,7 @@ declare class Connection extends EventEmitter {
996
995
  * Initiate graceful close of the connection.
997
996
  *
998
997
  * - If `CONNECTING` or `RECONNECTING`: cancels the pending attempt, transitions
999
- * directly to `CLOSED`, and calls `transport.destroy()` (LIFE-05).
998
+ * directly to `CLOSED`, and calls `transport.destroy()`.
1000
999
  * - If `CONNECTED`: transitions to `DRAINING`, calls `beforeClose(drainTimeoutMs)`,
1001
1000
  * then `DRAINING → DISCONNECTED` once the hook resolves, or `DRAINING → CLOSED`
1002
1001
  * if the drain timeout elapses first.
@@ -1017,7 +1016,7 @@ declare class Connection extends EventEmitter {
1017
1016
  * Race `beforeClose()` against the drain timeout.
1018
1017
  *
1019
1018
  * On normal completion: `DRAINING → DISCONNECTED` + `transport.close()`.
1020
- * On timeout: `DRAINING → CLOSED` + `transport.destroy()` (T-03-04-01).
1019
+ * On timeout: `DRAINING → CLOSED` + `transport.destroy()`.
1021
1020
  */
1022
1021
  private _drainWithTimeout;
1023
1022
  /**
@@ -1036,7 +1035,7 @@ declare class Connection extends EventEmitter {
1036
1035
  */
1037
1036
  destroy(reason?: Error): void;
1038
1037
  /**
1039
- * Return a JSON-serializable observability snapshot (OBS-03/04/05).
1038
+ * Return a JSON-serializable observability snapshot.
1040
1039
  *
1041
1040
  * All timestamp fields are `Date | null` (not epoch milliseconds). `JSON.stringify()`
1042
1041
  * serialises them to ISO 8601 strings with no information loss.
@@ -1133,9 +1132,9 @@ declare class Connection extends EventEmitter {
1133
1132
  /**
1134
1133
  * Connection lifecycle phase where the error occurred.
1135
1134
  *
1136
- * All 5 phases are defined in Phase 3 even though `'reconnect'` is only
1137
- * exercised in Phase 5 (CLIENT-17). Locking the full union now prevents a
1138
- * breaking type change later (ERR-03).
1135
+ * All 5 phases are defined even though `'reconnect'` is only
1136
+ * exercised by the client. Locking the full union now prevents a
1137
+ * breaking type change later.
1139
1138
  */
1140
1139
  type ConnectionErrorPhase = "connect" | "send" | "receive" | "close" | "reconnect";
1141
1140
  /**
@@ -1146,18 +1145,18 @@ type ConnectionErrorPhase = "connect" | "send" | "receive" | "close" | "reconnec
1146
1145
  * removing a member is a breaking change.
1147
1146
  *
1148
1147
  * - `'fifo-unsafe'`, A queued send was rejected during reconnect because
1149
- * FIFO ordering cannot be safely resumed across sessions (CLIENT-17).
1148
+ * FIFO ordering cannot be safely resumed across sessions.
1150
1149
  * - `'in-flight-orphan'`, An in-flight send (already write-flushed,
1151
1150
  * ACK timer started) was rejected during reconnect in FIFO mode because
1152
1151
  * the at-most-once delivery contract cannot be preserved across a
1153
- * socket drop (D-08, healthcare medication/orders semantics).
1154
- * - `'tls-verify'` (Phase 8), The TLS handshake failed certificate
1152
+ * socket drop (healthcare medication/orders semantics).
1153
+ * - `'tls-verify'`, The TLS handshake failed certificate
1155
1154
  * verification (untrusted chain, expired/not-yet-valid cert, hostname
1156
1155
  * mismatch, revocation, …). See {@link isTlsVerificationErrorCode} for the
1157
1156
  * exact underlying error codes. Classified **permanent** by
1158
1157
  * `isTransientConnectionError`, never auto-reconnect-looped into a
1159
1158
  * misconfigured or MITM'd endpoint.
1160
- * - `'tls-handshake'` (Phase 8), A TLS-**protocol**-shaped handshake
1159
+ * - `'tls-handshake'`, A TLS-**protocol**-shaped handshake
1161
1160
  * failure observed before `'secureConnect'`: `ERR_SSL_*` codes, `EPROTO`,
1162
1161
  * or an OpenSSL alert-bearing error (protocol version mismatch, no shared
1163
1162
  * cipher, a required mutual-TLS client certificate rejected by the
@@ -1352,8 +1351,8 @@ declare function resolveNackCode(err: unknown): NegativeAckCode;
1352
1351
  * 3. **A batch or concatenated messages.** An `FHS`/`BHS`/`BTS`/`FTS` envelope (§2.10.3)
1353
1352
  * or a second `MSH` in the same frame: a single MSA-2 can echo only ONE control ID, so
1354
1353
  * a positive ACK naming the first silently drops the rest (see
1355
- * {@link containsBatchOrExtraMessage}). Batch ACK is its own feature (`MLLP-BATCH`),
1356
- * until it is designed, a batch must stay a **loud non-positive** answer.
1354
+ * {@link containsBatchOrExtraMessage}). Batch ACK is its own feature; until it is
1355
+ * designed, a batch must stay a **loud non-positive** answer.
1357
1356
  *
1358
1357
  * This is a **refusal**, not a tolerance widening: it never makes an unreadable message
1359
1358
  * readable, never re-bases on a located `MSH`, never parses a batch. It only recognizes
@@ -1477,7 +1476,7 @@ declare function buildRawAck(payload: Buffer, code: AckCode): Buffer;
1477
1476
  */
1478
1477
 
1479
1478
  /**
1480
- * Metadata attached to each decoded MLLP message (SERVER-03).
1479
+ * Metadata attached to each decoded MLLP message.
1481
1480
  *
1482
1481
  * All fields are `readonly`, the object is `Object.freeze()`'d before emission.
1483
1482
  *
@@ -1541,10 +1540,10 @@ interface NackEvent {
1541
1540
  readonly reason: NackReason;
1542
1541
  }
1543
1542
  /**
1544
- * Observability snapshot returned by `server.getStats()` (OBS-02).
1543
+ * Observability snapshot returned by `server.getStats()`.
1545
1544
  *
1546
1545
  * All fields are JSON-serializable. `connections` and `activeConnections` both
1547
- * reflect the current live connection count (ROADMAP SC-5 / OBS-02).
1546
+ * reflect the current live connection count.
1548
1547
  *
1549
1548
  * @example
1550
1549
  * ```typescript
@@ -1560,7 +1559,7 @@ interface ServerStats {
1560
1559
  /** Bound host, or `null` before listen(). */
1561
1560
  readonly host: string | null;
1562
1561
  /**
1563
- * Current live connection count (OBS-02, ROADMAP SC-5).
1562
+ * Current live connection count.
1564
1563
  * Same value as `activeConnections`.
1565
1564
  */
1566
1565
  readonly connections: number;
@@ -1574,9 +1573,9 @@ interface ServerStats {
1574
1573
  readonly acceptedTotal: number;
1575
1574
  /** Total connections closed since listen() (monotonically increasing). */
1576
1575
  readonly closedTotal: number;
1577
- /** Whether this server is configured for TLS (Phase 8). Mirrors `ServerOptions.tls` being set. */
1576
+ /** Whether this server is configured for TLS. Mirrors `ServerOptions.tls` being set. */
1578
1577
  readonly tls: boolean;
1579
- /** Total `'tlsClientError'` events (failed TLS handshakes, incl. rejected client certs) since listen() (Phase 8). */
1578
+ /** Total `'tlsClientError'` events (failed TLS handshakes, incl. rejected client certs) since listen(). */
1580
1579
  readonly tlsClientErrorsTotal: number;
1581
1580
  }
1582
1581
  /**
@@ -1616,7 +1615,7 @@ interface ServerOptions {
1616
1615
  */
1617
1616
  onMessage?: (payload: Buffer, meta: MessageMeta, conn: Connection) => void | Promise<void>;
1618
1617
  /**
1619
- * FrameReader tolerance options applied to every accepted connection (SERVER-12).
1618
+ * FrameReader tolerance options applied to every accepted connection.
1620
1619
  * Merged with SERVER_DEFAULT_FRAMING, caller-supplied values override defaults.
1621
1620
  * `onFrame` and `onWarning` are managed internally and must not be supplied here.
1622
1621
  */
@@ -1641,31 +1640,31 @@ interface ServerOptions {
1641
1640
  * - **`fn`**, `fn(payload, meta, conn)` builds the ACK bytes the server sends; the
1642
1641
  * caller fully owns MSA-1 (e.g. to emit enhanced-mode `CA`/`CE`/`CR`).
1643
1642
  *
1644
- * The `'message'` event always fires BEFORE the ACK is sent (D-03). Do NOT call
1643
+ * The `'message'` event always fires BEFORE the ACK is sent. Do NOT call
1645
1644
  * `conn.send()` in `onMessage` when `autoAck` is set, this results in two ACKs.
1646
1645
  */
1647
1646
  autoAck?: "AA" | ((payload: Buffer, meta: MessageMeta, conn: Connection) => Buffer | Promise<Buffer>);
1648
1647
  /**
1649
- * TCP keepalive probe interval in ms (D-10).
1648
+ * TCP keepalive probe interval in ms.
1650
1649
  * Calls `socket.setKeepAlive(true, ms)` on each accepted socket.
1651
1650
  * Uses OS TCP stack to detect dead peers (half-open, network partitions).
1652
1651
  * Distinct from `deadPeerTimeoutMs` (application-level idle close).
1653
1652
  */
1654
1653
  keepaliveIntervalMs?: number;
1655
1654
  /**
1656
- * Application-level idle close timeout in ms (D-11, ROADMAP SC-5).
1655
+ * Application-level idle close timeout in ms.
1657
1656
  * If no HL7 messages are received on a connection for this interval, the connection
1658
1657
  * is destroyed via `conn.destroy(new Error('idle timeout'))`.
1659
1658
  * Resets on every `'message'` event. Distinct from `keepaliveIntervalMs` (OS TCP probe).
1660
1659
  */
1661
1660
  deadPeerTimeoutMs?: number;
1662
1661
  /**
1663
- * Graceful drain timeout passed to `conn.close()` during `server.close()` (D-06).
1662
+ * Graceful drain timeout passed to `conn.close()` during `server.close()`.
1664
1663
  * Default: 30 000 ms.
1665
1664
  */
1666
1665
  drainTimeoutMs?: number;
1667
1666
  /**
1668
- * Enable TLS (MLLPS) for this server (Phase 8). When set, the server binds a
1667
+ * Enable TLS (MLLPS) for this server. When set, the server binds a
1669
1668
  * `tls.Server` instead of a plain `net.Server`, consumes `'secureConnection'`
1670
1669
  * (post-handshake sockets) instead of `'connection'`, and surfaces failed
1671
1670
  * handshakes via the `'tlsClientError'` event rather than crashing.
@@ -1676,8 +1675,8 @@ interface ServerOptions {
1676
1675
  */
1677
1676
  tls?: ServerTlsOptions;
1678
1677
  /**
1679
- * Opt-in required to bind a wildcard host, a bind-safety guardrail
1680
- * (Phase 8). Without this flag, `listen()` rejects a wildcard host in
1678
+ * Opt-in required to bind a wildcard host, a bind-safety guardrail.
1679
+ * Without this flag, `listen()` rejects a wildcard host in
1681
1680
  * two tiers: **literal spellings** (`'0.0.0.0'`, `'::'`, `''`, `'::0'`,
1682
1681
  * `'0:0:0:0:0:0:0:0'`, `'::ffff:0.0.0.0'`, …) reject **pre-bind** (fast
1683
1682
  * path, nothing is ever bound); **resolver-only shorthands** (`'0'`,
@@ -1694,7 +1693,7 @@ interface ServerOptions {
1694
1693
  allowWildcardBind?: boolean;
1695
1694
  }
1696
1695
  /**
1697
- * Options for `createStarterServer()`, the "three lines of code" factory (SERVER-08).
1696
+ * Options for `createStarterServer()`, the "three lines of code" factory.
1698
1697
  *
1699
1698
  * Extends `ServerOptions` with `port`, `host`, and `handleSignals`. Defaults:
1700
1699
  * `autoAck: 'AA'`, `drainTimeoutMs: 30_000`, `Symbol.asyncDispose` wired.
@@ -1715,14 +1714,14 @@ interface StarterServerOptions extends ServerOptions {
1715
1714
  /** Port to listen on. */
1716
1715
  port: number;
1717
1716
  /**
1718
- * Host to bind to. Default `'127.0.0.1'` (Phase 8 bind-safety hardening,
1717
+ * Host to bind to. Default `'127.0.0.1'` (bind-safety hardening,
1719
1718
  * was `'0.0.0.0'`; binding all interfaces now requires
1720
1719
  * `ServerOptions.allowWildcardBind: true`).
1721
1720
  */
1722
1721
  host?: string;
1723
1722
  /**
1724
1723
  * Register `process.once('SIGTERM')` and `process.once('SIGINT')` handlers that
1725
- * call `server.close()` then `process.exit(0)` (D-09). Default: `false`.
1724
+ * call `server.close()` then `process.exit(0)`. Default: `false`.
1726
1725
  *
1727
1726
  * Handlers are automatically removed when `server.close()` is called, so
1728
1727
  * `process.listenerCount('SIGTERM') === 0` after close() completes, preventing
@@ -1731,7 +1730,7 @@ interface StarterServerOptions extends ServerOptions {
1731
1730
  handleSignals?: boolean;
1732
1731
  }
1733
1732
  /**
1734
- * MLLP TCP server, wraps `net.Server` without extending it (D-02).
1733
+ * MLLP TCP server, wraps `net.Server` without extending it.
1735
1734
  *
1736
1735
  * Each accepted socket is wrapped in a `NetTransport`, connected to a `Connection`
1737
1736
  * with server-level framing options, and added to `_connections`. Messages are
@@ -1756,10 +1755,10 @@ interface StarterServerOptions extends ServerOptions {
1756
1755
  * during the bind window changes the `listen()` rejection from the bind error to the typed
1757
1756
  * close-during-listen `MllpConnectionError`, match on the `'error'` event payload, not the
1758
1757
  * rejection, if you do that.
1759
- * Phase 8 (TLS/MLLPS) adds two more: `'tlsClientError'` (a failed TLS handshake, the
1758
+ * TLS (MLLPS) adds two more: `'tlsClientError'` (a failed TLS handshake, the
1760
1759
  * server logs it and keeps serving other connections) and `'securityWarning'` (loud,
1761
1760
  * one-time notice when a wildcard host is bound via `allowWildcardBind: true`).
1762
- * All event payloads are `Object.freeze()`'d before emission (SERVER-10).
1761
+ * All event payloads are `Object.freeze()`'d before emission.
1763
1762
  *
1764
1763
  * @example
1765
1764
  * ```typescript
@@ -1781,10 +1780,10 @@ declare class MllpServer extends EventEmitter {
1781
1780
  /** `true` when `ServerOptions.tls` is set, `_netServer` is actually a `tls.Server`. */
1782
1781
  private readonly _isTls;
1783
1782
  private _listening;
1784
- /** Phase 8, single-flight guard: `true` while a `listen()` call is settling. */
1783
+ /** Single-flight guard: `true` while a `listen()` call is settling. */
1785
1784
  private _listenInFlight;
1786
1785
  /**
1787
- * Phase 8, settle hook for an in-flight `listen()`. Non-null only while a
1786
+ * Settle hook for an in-flight `listen()`. Non-null only while a
1788
1787
  * `listen()` is in flight; invoked by `close()` so a close racing startup
1789
1788
  * rejects the pending `listen()` (typed) instead of leaving it hung with
1790
1789
  * the single-flight guard stuck. Cleared on every settle path.
@@ -1794,7 +1793,7 @@ declare class MllpServer extends EventEmitter {
1794
1793
  private _host;
1795
1794
  private _acceptedTotal;
1796
1795
  private _closedTotal;
1797
- /** Phase 8, count of `'tlsClientError'` events since listen(). */
1796
+ /** Count of `'tlsClientError'` events since listen(). */
1798
1797
  private _tlsClientErrorsTotal;
1799
1798
  /**
1800
1799
  * Construct an MLLP server. Created idle; call `listen()` (or use
@@ -1825,7 +1824,7 @@ declare class MllpServer extends EventEmitter {
1825
1824
  *
1826
1825
  * @param port - TCP port to bind. Use `0` to let the OS assign an ephemeral port.
1827
1826
  * @param hostOrOpts - Host string or object with `host` and optional `signal`.
1828
- * Default host: `'127.0.0.1'` (Phase 8 bind-safety hardening). Wildcard hosts
1827
+ * Default host: `'127.0.0.1'` (bind-safety hardening). Wildcard hosts
1829
1828
  * are rejected unless `ServerOptions.allowWildcardBind: true`, literal
1830
1829
  * spellings pre-bind, resolver-only shorthands post-bind via the
1831
1830
  * OS-normalized bound address.
@@ -1844,7 +1843,7 @@ declare class MllpServer extends EventEmitter {
1844
1843
  /**
1845
1844
  * Stop accepting new connections and gracefully close all active connections.
1846
1845
  *
1847
- * Sequence (D-06):
1846
+ * Sequence:
1848
1847
  * 1. `net.Server.close()`, stops accepting new connections immediately
1849
1848
  * 2. If `_connections` is empty: resolves immediately (no drain needed)
1850
1849
  * 3. Calls `_drainAll(drainTimeoutMs)`, Promise.all + side-effect setTimeout
@@ -1896,10 +1895,9 @@ declare class MllpServer extends EventEmitter {
1896
1895
  */
1897
1896
  [Symbol.asyncDispose](): Promise<void>;
1898
1897
  /**
1899
- * Return a JSON-serializable observability snapshot (OBS-02).
1898
+ * Return a JSON-serializable observability snapshot.
1900
1899
  *
1901
1900
  * `totalBytesIn` and `totalBytesOut` aggregate from live connections at call time.
1902
- * Plan 04 adds full aggregation; at Plan 01 scope they return 0.
1903
1901
  *
1904
1902
  * @example
1905
1903
  * ```typescript
@@ -1931,8 +1929,8 @@ declare class MllpServer extends EventEmitter {
1931
1929
  private _emitErrorIfListened;
1932
1930
  private _onSocketAccepted;
1933
1931
  /**
1934
- * Extract a minimal, content-free peer-certificate summary (Phase 8, ATNA
1935
- * ITI-19 mutual authentication), CN strings, expiry, and the verification
1932
+ * Extract a minimal, content-free peer-certificate summary (ATNA ITI-19
1933
+ * mutual authentication), CN strings, expiry, and the verification
1936
1934
  * outcome (`authorized`) only; never the full certificate object. Returns
1937
1935
  * `null` when no peer certificate was presented (e.g. `clientAuth: 'WANT'`
1938
1936
  * with no client cert).
@@ -1983,20 +1981,20 @@ declare class MllpServer extends EventEmitter {
1983
1981
  * Run `onMessage` for its side effects only (custom-ACK and manual modes), guarding
1984
1982
  * against a synchronous throw or a rejected promise. In these modes the handler does
1985
1983
  * **not** gate the ACK, so a failure is re-emitted as a PHI-safe `'error'` on the
1986
- * connection (D-04: a handler error never crashes the server) rather than escaping as
1984
+ * connection (a handler error never crashes the server) rather than escaping as
1987
1985
  * an unhandled rejection. The error text is never placed on the wire.
1988
1986
  */
1989
1987
  private _observeMessage;
1990
1988
  /**
1991
1989
  * The custom-builder path for `autoAck: fn`. Awaits the builder and dispatches its
1992
1990
  * Buffer as the ACK; the caller owns MSA-1. A builder error is re-emitted as `'error'`
1993
- * on the connection, the server never crashes (D-04).
1991
+ * on the connection, the server never crashes.
1994
1992
  */
1995
1993
  private _sendCustomAck;
1996
1994
  /**
1997
1995
  * Frame an ACK payload and write it to the connection. `Connection.send()` returns
1998
1996
  * `false` under backpressure (socket write buffer full); that drops the ACK and emits
1999
- * a `MllpConnectionError({ phase: 'send' })` on the connection (D-04), the peer will
1997
+ * a `MllpConnectionError({ phase: 'send' })` on the connection, the peer will
2000
1998
  * time out waiting and may retry. The server never crashes.
2001
1999
  */
2002
2000
  private _dispatchAck;
@@ -2025,8 +2023,6 @@ declare function createServer(opts?: ServerOptions): MllpServer;
2025
2023
  * Provides the "three lines of code" north-star experience with sensible defaults:
2026
2024
  * `autoAck: 'AA'`, `drainTimeoutMs: 30_000`, `Symbol.asyncDispose` wired.
2027
2025
  *
2028
- * NOTE: Stub at Plan 01 scope, Plan 04 fills in the full implementation.
2029
- *
2030
2026
  * @example
2031
2027
  * ```typescript
2032
2028
  * import { createStarterServer } from '@cosyte/mllp';
@@ -2047,11 +2043,8 @@ declare function createStarterServer(opts: StarterServerOptions): Promise<MllpSe
2047
2043
  * events with frozen payloads. Supports `AbortSignal` cancellation on every
2048
2044
  * awaitable and `Symbol.asyncDispose` for `await using` ergonomics.
2049
2045
  *
2050
- * Phase 5 PLAN-01 shipped the lifecycle scaffolding, `connect()`, `close()`,
2051
- * `destroy()`, event re-emission. PLAN-02 added `send()` + `MllpTimeoutError`.
2052
- * The `correlateByControlId` option (MSH-10 → MSA-2 ACK matching) lights up
2053
- * out-of-order ACK handling. Subsequent plans add auto-reconnect (Plan 04),
2054
- * backpressure (Plan 05), and `createStarterClient` + `getStats()` (PLAN-06).
2046
+ * The `correlateByControlId` option (MSH-10 → MSA-2 ACK matching) enables
2047
+ * out-of-order ACK handling.
2055
2048
  *
2056
2049
  * @example
2057
2050
  * ```typescript
@@ -2059,7 +2052,7 @@ declare function createStarterServer(opts: StarterServerOptions): Promise<MllpSe
2059
2052
  *
2060
2053
  * const client = createClient({ host: 'localhost', port: 2575 });
2061
2054
  * await client.connect();
2062
- * // PLAN-02 will add: const ack = await client.send(payloadBuffer);
2055
+ * const ack = await client.send(payloadBuffer);
2063
2056
  * await client.close();
2064
2057
  * ```
2065
2058
  *
@@ -2067,11 +2060,9 @@ declare function createStarterServer(opts: StarterServerOptions): Promise<MllpSe
2067
2060
  */
2068
2061
 
2069
2062
  /**
2070
- * Context passed to a custom `retryStrategy` hook on each reconnect attempt
2071
- * (CLIENT-12, D-15).
2063
+ * Context passed to a custom `retryStrategy` hook on each reconnect attempt.
2072
2064
  *
2073
- * Frozen via `Object.freeze` before invocation, handlers cannot mutate
2074
- * (T-05-04-04 mitigation).
2065
+ * Frozen via `Object.freeze` before invocation, handlers cannot mutate.
2075
2066
  *
2076
2067
  * @example
2077
2068
  * ```typescript
@@ -2093,22 +2084,22 @@ interface RetryContext {
2093
2084
  readonly totalElapsedMs: number;
2094
2085
  /** Ms since the last successful ACK. `Infinity` if no success seen. */
2095
2086
  readonly sinceLastSuccessMs: number;
2096
- /** CLIENT-18 classification (Composition A, D-16). */
2087
+ /** How the failure that triggered this reconnect attempt was classified. */
2097
2088
  readonly classifiedAs: "transient" | "permanent";
2098
2089
  /**
2099
2090
  * The same `AbortSignal` passed into `connect()`. If no signal was
2100
2091
  * supplied, the module-level `NEVER_ABORTING_SIGNAL` sentinel is provided
2101
- * so handlers always have a real `AbortSignal` to inspect. (D-18, W-07)
2092
+ * so handlers always have a real `AbortSignal` to inspect.
2102
2093
  */
2103
2094
  readonly signal: AbortSignal;
2104
2095
  }
2105
2096
  /**
2106
- * Custom reconnect-backoff hook (CLIENT-12). Return `null` to halt
2107
- * reconnection (D-17), the FSM transitions to `CLOSED`.
2097
+ * Custom reconnect-backoff hook. Return `null` to halt
2098
+ * reconnection, the FSM transitions to `CLOSED`.
2108
2099
  */
2109
2100
  type RetryStrategy = (ctx: RetryContext) => number | null;
2110
2101
  /**
2111
- * Combined count + byte-based queue cap. Stricter-of-two wins (D-23).
2102
+ * Combined count + byte-based queue cap. Stricter-of-two wins.
2112
2103
  *
2113
2104
  * - `number`, count cap only (default 64).
2114
2105
  * - `{ bytes }`, byte cap only.
@@ -2129,8 +2120,6 @@ type HighWaterMark = number | {
2129
2120
  /**
2130
2121
  * Options for {@link createClient} and the {@link MllpClient} constructor.
2131
2122
  *
2132
- * Phase 5 plans extend this incrementally, new fields are additive and optional.
2133
- *
2134
2123
  * @example
2135
2124
  * ```typescript
2136
2125
  * const opts: ClientOptions = { host: 'localhost', port: 2575, drainTimeoutMs: 10_000 };
@@ -2146,54 +2135,54 @@ interface ClientOptions {
2146
2135
  /** Drain timeout for {@link MllpClient.close} (default: `30_000` ms). */
2147
2136
  readonly drainTimeoutMs?: number;
2148
2137
  /**
2149
- * Per-message ACK timeout in milliseconds (CLIENT-04). The clock starts at
2138
+ * Per-message ACK timeout in milliseconds. The clock starts at
2150
2139
  * the underlying `write()` flush callback, NOT at the `send()` call,
2151
2140
  * pre-flush queue time is not charged to the peer. Default: `30_000`.
2152
2141
  */
2153
2142
  readonly ackTimeoutMs?: number;
2154
2143
  /**
2155
- * If `true`, ACKs are matched against outgoing sends by MSH-10 → MSA-2
2156
- * (CLIENT-03 controlId branch). Default `false` (FIFO mode).
2144
+ * If `true`, ACKs are matched against outgoing sends by MSH-10 → MSA-2.
2145
+ * Default `false` (FIFO mode).
2157
2146
  *
2158
2147
  * Out-of-order ACKs from the peer are supported in this mode. MSH-10 is
2159
2148
  * extracted from the outbound payload before send; MSA-2 is extracted from
2160
2149
  * the inbound ACK payload. An ACK whose MSA-2 matches no pending send
2161
2150
  * (and is not in the late-ACK graveyard) emits a frozen
2162
- * `MllpFramingError('MLLP_ACK_UNMATCHED_CONTROL_ID')` to the `'error'` event
2163
- * (CLIENT-15). A late ACK whose MSA-2 matches a graveyard entry emits a
2164
- * `MLLP_ACK_AFTER_TIMEOUT` warning (CLIENT-16) and is dropped.
2151
+ * `MllpFramingError('MLLP_ACK_UNMATCHED_CONTROL_ID')` to the `'error'` event.
2152
+ * A late ACK whose MSA-2 matches a graveyard entry emits a
2153
+ * `MLLP_ACK_AFTER_TIMEOUT` warning and is dropped.
2165
2154
  *
2166
2155
  * @default false
2167
2156
  */
2168
2157
  readonly correlateByControlId?: boolean;
2169
2158
  /**
2170
- * Auto-reconnect on transient disconnect (CLIENT-05). Default `false`.
2159
+ * Auto-reconnect on transient disconnect. Default `false`.
2171
2160
  *
2172
2161
  * When `true`, dropped connections caused by transient errors (per
2173
2162
  * {@link isTransientConnectionError}) trigger the FSM cycle
2174
2163
  * `CONNECTED → DISCONNECTED → RECONNECTING → CONNECTING → CONNECTED`
2175
- * with exponential backoff per D-19 unless overridden by
2164
+ * with exponential backoff unless overridden by
2176
2165
  * {@link ClientOptions.retryStrategy}. Permanent errors halt and
2177
- * transition directly to `CLOSED` (Composition A, D-16).
2166
+ * transition directly to `CLOSED`.
2178
2167
  */
2179
2168
  readonly autoReconnect?: boolean;
2180
2169
  /**
2181
- * Custom reconnect-backoff hook (CLIENT-12, D-15). Return `null` to halt
2182
- * reconnection (D-17). Receives a frozen {@link RetryContext}. Defaults
2183
- * to the exponential strategy described in D-19.
2170
+ * Custom reconnect-backoff hook. Return `null` to halt
2171
+ * reconnection. Receives a frozen {@link RetryContext}. Defaults
2172
+ * to the exponential strategy.
2184
2173
  */
2185
2174
  readonly retryStrategy?: RetryStrategy;
2186
- /** First delay (ms) on auto-reconnect; default 100. (CLIENT-05, D-19) */
2175
+ /** First delay (ms) on auto-reconnect; default 100. */
2187
2176
  readonly initialDelayMs?: number;
2188
- /** Maximum backoff cap (ms); default 30_000. (CLIENT-05, D-19) */
2177
+ /** Maximum backoff cap (ms); default 30_000. */
2189
2178
  readonly maxDelayMs?: number;
2190
- /** Backoff multiplier; default 2. (CLIENT-05, D-19) */
2179
+ /** Backoff multiplier; default 2. */
2191
2180
  readonly multiplier?: number;
2192
- /** Jitter fraction, e.g. 0.2 = ±20%; default 0.2. (CLIENT-05, D-19) */
2181
+ /** Jitter fraction, e.g. 0.2 = ±20%; default 0.2. */
2193
2182
  readonly jitter?: number;
2194
2183
  /**
2195
- * Application-level high-water mark on the in-flight + queued send set
2196
- * (CLIENT-07, D-23). `number` configures a count cap (default 64);
2184
+ * Application-level high-water mark on the in-flight + queued send set.
2185
+ * `number` configures a count cap (default 64);
2197
2186
  * `{ bytes }` configures a byte cap; `{ count, bytes }` configures
2198
2187
  * both, with the stricter-of-two trigger winning.
2199
2188
  *
@@ -2204,17 +2193,17 @@ interface ClientOptions {
2204
2193
  */
2205
2194
  readonly highWaterMark?: HighWaterMark;
2206
2195
  /**
2207
- * Behavior when the high-water mark is exceeded (CLIENT-07).
2196
+ * Behavior when the high-water mark is exceeded.
2208
2197
  *
2209
2198
  * - `'reject'` (default), `send()` rejects with `MllpBackpressureError`.
2210
2199
  * - `'wait'`, `send()` awaits the `'drain'` event OR the per-message
2211
- * `ackTimeoutMs` OR `signal` abort, whichever fires first (CLIENT-11).
2200
+ * `ackTimeoutMs` OR `signal` abort, whichever fires first.
2212
2201
  *
2213
2202
  * @default 'reject'
2214
2203
  */
2215
2204
  readonly onBackpressure?: "reject" | "wait";
2216
2205
  /**
2217
- * Strict serialization send → await-ACK → send (CLIENT-19, D-06).
2206
+ * Strict serialization send → await-ACK → send.
2218
2207
  *
2219
2208
  * - `true` (default), concurrent in-flight sends up to
2220
2209
  * {@link ClientOptions.highWaterMark}.
@@ -2229,23 +2218,23 @@ interface ClientOptions {
2229
2218
  * TCP keepalive interval (ms). Sets `socket.setKeepAlive(true, ms)` on
2230
2219
  * the underlying `net.Socket` BEFORE wrapping in `NetTransport`. OS-level
2231
2220
  * half-open detection (network partitions, NAT-table eviction). Independent
2232
- * of {@link ClientOptions.deadPeerTimeoutMs} (CLIENT-08, D-11/A3).
2221
+ * of {@link ClientOptions.deadPeerTimeoutMs}.
2233
2222
  *
2234
2223
  * @default undefined (off)
2235
2224
  */
2236
2225
  readonly keepaliveIntervalMs?: number;
2237
2226
  /**
2238
- * Application-idle timeout (ms) keyed on last inbound bytes / ACK / warning
2239
- * (CLIENT-08, D-11). On trip, calls `connection.destroy(new Error('dead
2227
+ * Application-idle timeout (ms) keyed on last inbound bytes / ACK / warning.
2228
+ * On trip, calls `connection.destroy(new Error('dead
2240
2229
  * peer timeout'))` which surfaces as `MllpConnectionError({ phase: 'receive' })`.
2241
- * Trip honors {@link ClientOptions.autoReconnect} (D-13). Independent of
2242
- * {@link ClientOptions.keepaliveIntervalMs} (D-11/A3).
2230
+ * Trip honors {@link ClientOptions.autoReconnect}. Independent of
2231
+ * {@link ClientOptions.keepaliveIntervalMs}.
2243
2232
  *
2244
2233
  * @default undefined (off)
2245
2234
  */
2246
2235
  readonly deadPeerTimeoutMs?: number;
2247
2236
  /**
2248
- * Enable TLS (MLLPS) for this connection (Phase 8). `true` enables TLS with
2237
+ * Enable TLS (MLLPS) for this connection. `true` enables TLS with
2249
2238
  * all defaults, including certificate verification **on**. Pass a
2250
2239
  * {@link TlsOptions} object to customize (`ca`/`cert`/`key`, minimum
2251
2240
  * version, ciphers, `allowUnverified`, …).
@@ -2257,16 +2246,16 @@ interface ClientOptions {
2257
2246
  readonly tls?: TlsOptions | true;
2258
2247
  }
2259
2248
  /**
2260
- * Observability snapshot returned by {@link MllpClient.getStats} (OBS-01, D-26).
2249
+ * Observability snapshot returned by {@link MllpClient.getStats}.
2261
2250
  *
2262
- * All fields are JSON-serializable (OBS-04), no Buffers, no class instances,
2251
+ * All fields are JSON-serializable, no Buffers, no class instances,
2263
2252
  * no Maps, no circular references. `lastConnectedAt` and `lastAckAt` are
2264
2253
  * **epoch milliseconds** (numbers), NOT `Date` instances, log-pipeline
2265
- * friendly per D-26.
2254
+ * friendly.
2266
2255
  *
2267
2256
  * `warningsByCode` keys are constrained to the public {@link WarningCode}
2268
2257
  * union, adding/removing a code is a breaking change (CLAUDE.md
2269
- * stable-codes guardrail enforced at the type boundary, B-05).
2258
+ * stable-codes guardrail enforced at the type boundary).
2270
2259
  *
2271
2260
  * @example
2272
2261
  * ```typescript
@@ -2288,7 +2277,7 @@ interface ClientStats {
2288
2277
  readonly inFlight: number;
2289
2278
  /**
2290
2279
  * Aggregated warning counts. Keys are constrained to the public
2291
- * {@link WarningCode} union (B-05). Connection-level warnings + Correlator
2280
+ * {@link WarningCode} union. Connection-level warnings + Correlator
2292
2281
  * `MLLP_ACK_*` warnings are merged.
2293
2282
  */
2294
2283
  readonly warningsByCode: Partial<Record<WarningCode, number>>;
@@ -2302,28 +2291,28 @@ interface ClientStats {
2302
2291
  readonly ackedTotal: number;
2303
2292
  /** Total ACK timeouts since construction. */
2304
2293
  readonly timedOutTotal: number;
2305
- /** Total reconnect attempts since construction (W-02). */
2294
+ /** Total reconnect attempts since construction. */
2306
2295
  readonly reconnectAttempts: number;
2307
2296
  /** Epoch ms of the last `CONNECTED` transition. `null` until first connect. */
2308
2297
  readonly lastConnectedAt: number | null;
2309
2298
  /** Epoch ms of the most recent successful ACK. `null` until first ACK. */
2310
2299
  readonly lastAckAt: number | null;
2311
- /** Whether this client is configured for TLS (Phase 8). Mirrors `ClientOptions.tls` being set. */
2300
+ /** Whether this client is configured for TLS. Mirrors `ClientOptions.tls` being set. */
2312
2301
  readonly tls: boolean;
2313
2302
  }
2314
2303
  /**
2315
- * MLLP client, composes a single Phase 3 {@link Connection} over a {@link NetTransport}
2304
+ * MLLP client, composes a single {@link Connection} over a {@link NetTransport}
2316
2305
  * (production) or any other `Transport` (testing via {@link InMemoryTransport}).
2317
2306
  *
2318
- * Public events, every payload `Object.freeze`'d before emission (D-25):
2307
+ * Public events, every payload `Object.freeze`'d before emission:
2319
2308
  * - `'stateChange'`, `{ from, to, reason? }` from the underlying Connection FSM
2320
2309
  * - `'connect'`, `{ connectionId }` once the FSM enters `CONNECTED`
2321
2310
  * - `'disconnect'`, `{ connectionId }` once the FSM enters `DISCONNECTED`
2322
- * - `'reconnecting'`, `{ connectionId, attempt?, delayMs? }` (Plan 04 populates)
2311
+ * - `'reconnecting'`, `{ connectionId, attempt?, delayMs? }`
2323
2312
  * - `'close'`, `{ connectionId }` once the FSM enters terminal `CLOSED`
2324
2313
  * - `'message'`, `{ payload, connectionId, byteOffset, warnings }` for every inbound frame
2325
2314
  * - `'warning'`, `MllpWarning` enriched with `connectionId` from the Connection layer
2326
- * - `'securityWarning'`, `SecurityWarning` (Phase 8). Emitted on every successful
2315
+ * - `'securityWarning'`, `SecurityWarning`. Emitted on every successful
2327
2316
  * `secureConnect` (initial + every reconnect) when `tls.allowUnverified` is `true`
2328
2317
  * with code `MLLP_TLS_VERIFY_DISABLED`. Also mirrored to `process.emitWarning`.
2329
2318
  * - `'error'`, re-emitted from Connection. Guarded by `listenerCount('error') > 0` so
@@ -2335,7 +2324,7 @@ interface ClientStats {
2335
2324
  * client.on('stateChange', ({ from, to }) => logger.info({ from, to }));
2336
2325
  * client.on('message', ({ payload }) => logger.info({ bytes: payload.length }));
2337
2326
  * await client.connect();
2338
- * // PLAN-02 will add: const ack = await client.send(payloadBuffer);
2327
+ * const ack = await client.send(payloadBuffer);
2339
2328
  * await client.close();
2340
2329
  * ```
2341
2330
  */
@@ -2348,15 +2337,15 @@ declare class MllpClient extends EventEmitter {
2348
2337
  * is attached, `state` mirrors `_connection.state`.
2349
2338
  */
2350
2339
  private _state;
2351
- /** Per-message ACK timeout in ms (CLIENT-04). Resolved at construction. */
2340
+ /** Per-message ACK timeout in ms. Resolved at construction. */
2352
2341
  private readonly _ackTimeoutMs;
2353
- /** controlId-mode flag (CLIENT-03 branch). `false` → FIFO. */
2342
+ /** controlId-mode flag. `false` → FIFO. */
2354
2343
  private readonly _correlateByControlId;
2355
- /** Unified ACK correlator (D-03/A1). Built during `_attachConnection`. */
2344
+ /** Unified ACK correlator. Built during `_attachConnection`. */
2356
2345
  private _correlator;
2357
2346
  /**
2358
2347
  * Periodic ACK-timeout sweep timer. Drives `_correlator.expireDue()` because
2359
- * the Correlator is timer-free per D-03. Cleared on close/destroy.
2348
+ * the Correlator is timer-free. Cleared on close/destroy.
2360
2349
  */
2361
2350
  private _ackSweepTimer;
2362
2351
  private readonly _autoReconnect;
@@ -2368,12 +2357,12 @@ declare class MllpClient extends EventEmitter {
2368
2357
  /** 0-indexed attempt counter for the current reconnect cycle. */
2369
2358
  private _attempt;
2370
2359
  /**
2371
- * W-02, total reconnect attempts since construction. Read by PLAN-06 for
2360
+ * Total reconnect attempts since construction, surfaced as
2372
2361
  * `getStats().reconnectAttempts`. Incremented at the entry of every
2373
2362
  * `_handleDisconnect` invocation that proceeds to schedule a backoff.
2374
2363
  */
2375
2364
  private _reconnectAttempts;
2376
- /** Epoch ms of the last successful ACK. Drives W-01 backoff-reset. */
2365
+ /** Epoch ms of the last successful ACK. Drives backoff-reset. */
2377
2366
  private _lastSuccessAt;
2378
2367
  /** Epoch ms when the current reconnect cycle began. `null` outside a cycle. */
2379
2368
  private _reconnectCycleStartedAt;
@@ -2389,12 +2378,12 @@ declare class MllpClient extends EventEmitter {
2389
2378
  private readonly _onBackpressure;
2390
2379
  /** Pipeline flag; default `true` (parallel up to highWaterMark). */
2391
2380
  private readonly _pipeline;
2392
- /** Dead-peer idle timer (Plan 05, D-11). `null` when not armed. */
2381
+ /** Dead-peer idle timer. `null` when not armed. */
2393
2382
  private _deadPeerTimer;
2394
2383
  /** True once the self-'ack' listener that resets the dead-peer timer
2395
2384
  * has been attached. Guards against duplicate listeners on reconnect. */
2396
2385
  private _ackResetWired;
2397
- /** Most recently bound `connect()` signal. Reread on every RetryContext build (W-07). */
2386
+ /** Most recently bound `connect()` signal. Reread on every RetryContext build. */
2398
2387
  private _connectSignal;
2399
2388
  /** Set when close()/destroy()/abort fires; reconnect handler short-circuits. */
2400
2389
  private _userClosed;
@@ -2422,7 +2411,7 @@ declare class MllpClient extends EventEmitter {
2422
2411
  /**
2423
2412
  * Aggregated Correlator-emitted warning counts (MLLP_ACK_*). Connection-level
2424
2413
  * warnings are read directly from `_connection.getStats().warningsByCode`
2425
- * at observation time and merged into the snapshot (D-26).
2414
+ * at observation time and merged into the snapshot.
2426
2415
  */
2427
2416
  private _aggregatedWarningsByCode;
2428
2417
  /**
@@ -2439,8 +2428,8 @@ declare class MllpClient extends EventEmitter {
2439
2428
  */
2440
2429
  get state(): ConnectionState;
2441
2430
  /**
2442
- * Open a TCP (or TLS, Phase 8) connection to the configured `host:port`
2443
- * and attach a Phase 3 {@link Connection} to it. Resolves once the FSM
2431
+ * Open a TCP (or TLS) connection to the configured `host:port`
2432
+ * and attach a {@link Connection} to it. Resolves once the FSM
2444
2433
  * enters `CONNECTED`, for TLS, on `'secureConnect'` (handshake complete,
2445
2434
  * including certificate verification when it is on).
2446
2435
  *
@@ -2483,7 +2472,7 @@ declare class MllpClient extends EventEmitter {
2483
2472
  * Build the raw socket + `Transport` pair for a connect / reconnect attempt.
2484
2473
  *
2485
2474
  * Plaintext (`ClientOptions.tls` unset): a `net.Socket` wrapped in
2486
- * `NetTransport`. TLS (Phase 8): a `tls.TLSSocket` wrapped in
2475
+ * `NetTransport`. TLS: a `tls.TLSSocket` wrapped in
2487
2476
  * `TlsTransport`, verification defaults **on**
2488
2477
  * (`rejectUnauthorized: !allowUnverified`), floor `minVersion: 'TLSv1.2'`
2489
2478
  * (the IHE ATNA ITI-19 BCP195 floor), `servername` defaulting to
@@ -2492,7 +2481,7 @@ declare class MllpClient extends EventEmitter {
2492
2481
  private _createSocketAndTransport;
2493
2482
  /**
2494
2483
  * Wrap a connect-phase socket error as `MllpConnectionError`, classifying
2495
- * TLS failures (Phase 8) into the additive `connectionCause`:
2484
+ * TLS failures into the additive `connectionCause`:
2496
2485
  *
2497
2486
  * - `'tls-verify'`, certificate-verification failures
2498
2487
  * ({@link isTlsVerificationErrorCode}).
@@ -2516,7 +2505,7 @@ declare class MllpClient extends EventEmitter {
2516
2505
  */
2517
2506
  private _emitContained;
2518
2507
  /**
2519
- * Emit the per-connection insecure-TLS warning (Phase 8) when
2508
+ * Emit the per-connection insecure-TLS warning when
2520
2509
  * `tls.allowUnverified === true`, fires on EVERY successful
2521
2510
  * `secureConnect`, initial connect and every reconnect. Emits both a frozen
2522
2511
  * `'securityWarning'` event and `process.emitWarning`. No-op for plaintext
@@ -2525,11 +2514,11 @@ declare class MllpClient extends EventEmitter {
2525
2514
  private _emitInsecureWarningIfNeeded;
2526
2515
  /**
2527
2516
  * Wire a Connection's events through to this MllpClient. Every re-emitted
2528
- * payload is `Object.freeze`'d before emission (D-25), even though the
2517
+ * payload is `Object.freeze`'d before emission, even though the
2529
2518
  * Connection layer already freezes, defense-in-depth, harmless on
2530
2519
  * already-frozen objects.
2531
2520
  *
2532
- * Builds the unified `Correlator` (D-03/A1) bound to this Connection and
2521
+ * Builds the unified `Correlator` bound to this Connection and
2533
2522
  * arms the periodic ACK-timeout sweep. The Correlator is teardown-aware:
2534
2523
  * `close()` / `destroy()` clear the sweep timer and reject pending sends.
2535
2524
  *
@@ -2537,37 +2526,36 @@ declare class MllpClient extends EventEmitter {
2537
2526
  */
2538
2527
  private _attachConnection;
2539
2528
  /**
2540
- * Arm (or re-arm) the dead-peer idle timer (Plan 05, CLIENT-08, D-11).
2529
+ * Arm (or re-arm) the dead-peer idle timer.
2541
2530
  * No-op when `deadPeerTimeoutMs` is unset.
2542
2531
  */
2543
2532
  private _armDeadPeerTimer;
2544
2533
  /**
2545
- * Clear the dead-peer idle timer (Plan 05, D-14 timer cleanup on
2546
- * every transition out of CONNECTED).
2534
+ * Clear the dead-peer idle timer on every transition out of CONNECTED.
2547
2535
  */
2548
2536
  private _clearDeadPeerTimer;
2549
2537
  /**
2550
- * Disconnect handler, Plan 04 reconnect FSM core.
2538
+ * Disconnect handler, reconnect FSM core.
2551
2539
  *
2552
2540
  * Implements:
2553
- * - CLIENT-17 hybrid in-flight handling (D-08): controlId mode preserves
2541
+ * - Hybrid in-flight handling: controlId mode preserves
2554
2542
  * pending sends for resend; FIFO mode rejects in-flight with
2555
2543
  * `connectionCause: 'in-flight-orphan'` and queued with `'fifo-unsafe'`.
2556
- * - CLIENT-18 classifier-first (Composition A, D-16): permanent errors
2544
+ * - Classifier-first: permanent errors
2557
2545
  * transition straight to CLOSED without invoking `retryStrategy`.
2558
- * - W-01 backoff-reset on recent success: first disconnect after a
2546
+ * - Backoff-reset on recent success: first disconnect after a
2559
2547
  * successful ACK on the prior session resets `_attempt` to 0.
2560
- * - W-02 `_reconnectAttempts` counter increment.
2561
- * - D-15 frozen RetryContext + D-17 null-return halts.
2562
- * - D-19 default exponential strategy.
2548
+ * - `_reconnectAttempts` counter increment.
2549
+ * - Frozen RetryContext; a `null` return from the strategy halts reconnection.
2550
+ * - Default exponential strategy.
2563
2551
  *
2564
- * Invoked from the SINGLE `_onStateChange` hook, no parallel listener
2565
- * (B-04). Idempotent across same-cycle re-entry: cycle-start flag
2552
+ * Invoked from the SINGLE `_onStateChange` hook, no parallel listener.
2553
+ * Idempotent across same-cycle re-entry: cycle-start flag
2566
2554
  * coordinates first-disconnect vs subsequent-within-cycle behavior.
2567
2555
  */
2568
2556
  private _handleDisconnect;
2569
2557
  /**
2570
- * Default retry strategy (D-19): `min(maxDelay, initialDelay * multiplier^attempt)`
2558
+ * Default retry strategy: `min(maxDelay, initialDelay * multiplier^attempt)`
2571
2559
  * with ±jitter applied.
2572
2560
  */
2573
2561
  private _defaultRetryStrategy;
@@ -2603,7 +2591,7 @@ declare class MllpClient extends EventEmitter {
2603
2591
  arm: () => void;
2604
2592
  }): void;
2605
2593
  /**
2606
- * Test seam, capture or rebind the connect-signal mid-flight (W-07).
2594
+ * Test seam, capture or rebind the connect-signal mid-flight.
2607
2595
  *
2608
2596
  * @internal
2609
2597
  */
@@ -2613,28 +2601,25 @@ declare class MllpClient extends EventEmitter {
2613
2601
  *
2614
2602
  * - FIFO mode: passes `null` controlId so `matchAck` returns the head of
2615
2603
  * the live store.
2616
- * - controlId mode: extracts MSA-2 at the `HOOK_EXTENSION_POINT: ack-payload`
2617
- * anchor and passes it to `matchAck` for keyed lookup.
2604
+ * - controlId mode: extracts MSA-2 and passes it to `matchAck` for keyed
2605
+ * lookup.
2618
2606
  *
2619
2607
  * Called from the SINGLE `'message'` listener registered in `_attachConnection`.
2620
- * No parallel listener is registered, downstream plans extend at the named
2621
- * anchor (B-04).
2608
+ * No parallel listener is registered.
2622
2609
  */
2623
2610
  private _onAckPayload;
2624
2611
  /**
2625
2612
  * Single source-of-truth for a successfully matched ACK (live-store hit).
2626
2613
  *
2627
- * PLAN-02: emit frozen 'ack' event, call matched.resolve().
2628
- * Plan 04 extends at HOOK_EXTENSION_POINT: ack-matched to update _lastSuccessAt.
2629
- * PLAN-06 extends at HOOK_EXTENSION_POINT: ack-matched to bump _ackedTotal and
2630
- * set _lastAckAt.
2614
+ * Emits the frozen 'ack' event and resolves the pending send. Updates
2615
+ * `_lastSuccessAt`, `_ackedTotal` and `_lastAckAt`.
2631
2616
  *
2632
2617
  * Called from _onAckPayload when matchAck() returns a non-null PendingAck.
2633
2618
  */
2634
2619
  private _onAckMatched;
2635
2620
  /**
2636
2621
  * Emit a frozen `'drain'` event when the queue depth and bytes fall below
2637
- * both configured caps (Plan 05, D-24). Called from `_onAckMatched`
2622
+ * both configured caps. Called from `_onAckMatched`
2638
2623
  * (every successful ACK) and from the Correlator's `onTimeout` callback
2639
2624
  * (every expired send), both code paths free a live-store slot.
2640
2625
  */
@@ -2642,28 +2627,24 @@ declare class MllpClient extends EventEmitter {
2642
2627
  /**
2643
2628
  * Single source-of-truth for Connection FSM transitions.
2644
2629
  *
2645
- * PLAN-02: re-emit frozen 'stateChange' (was inline in PLAN-01; centralized
2646
- * here so Plan 04 / Plan 05 can extend at named anchors).
2647
- * Plan 04 extends at HOOK_EXTENSION_POINT: state-change to detect
2648
- * CONNECTED → DISCONNECTED|RECONNECTING and trigger _handleDisconnect.
2649
- * Plan 05 extends at HOOK_EXTENSION_POINT: state-change to clear/arm
2650
- * dead-peer timer on transitions out of / into CONNECTED.
2630
+ * Re-emits a frozen 'stateChange' event, detects
2631
+ * CONNECTED → DISCONNECTED|RECONNECTING to trigger `_handleDisconnect`, and
2632
+ * clears or arms the dead-peer timer on transitions out of / into CONNECTED.
2651
2633
  *
2652
2634
  * Called from the SINGLE 'stateChange' listener registered in _attachConnection.
2653
2635
  */
2654
2636
  private _onStateChange;
2655
2637
  /**
2656
- * Send an MLLP-framed payload and await the inbound ACK (CLIENT-02).
2638
+ * Send an MLLP-framed payload and await the inbound ACK.
2657
2639
  *
2658
2640
  * Resolves with the ACK Buffer (framing stripped). Rejects with:
2659
- * - `DOMException('Aborted', 'AbortError')` if `signal` aborts before ACK
2660
- * (CLIENT-11 send branch).
2661
- * - `MllpTimeoutError` if no ACK arrives within `ackTimeoutMs` (ERR-02).
2641
+ * - `DOMException('Aborted', 'AbortError')` if `signal` aborts before the ACK.
2642
+ * - `MllpTimeoutError` if no ACK arrives within `ackTimeoutMs`.
2662
2643
  * The clock starts at the underlying `write()` flush callback, NOT at
2663
- * the `send()` call (CLIENT-04, D-19).
2644
+ * the `send()` call.
2664
2645
  * - `MllpConnectionError({ phase: 'send' })` if the client is not connected.
2665
2646
  *
2666
- * Emits a frozen `'ack'` event on every successful match (D-25 + Specifics).
2647
+ * Emits a frozen `'ack'` event on every successful match.
2667
2648
  *
2668
2649
  * @example
2669
2650
  * ```typescript
@@ -2672,19 +2653,19 @@ declare class MllpClient extends EventEmitter {
2672
2653
  * ```
2673
2654
  *
2674
2655
  * @param payload Raw bytes; MLLP framing is added internally via `encodeFrame`.
2675
- * @param opts.signal AbortSignal, aborting cancels the ACK wait (CLIENT-11).
2656
+ * @param opts.signal AbortSignal, aborting cancels the ACK wait.
2676
2657
  */
2677
2658
  send(payload: Buffer, opts?: {
2678
2659
  signal?: AbortSignal;
2679
2660
  ackTimeoutMs?: number;
2680
2661
  }): Promise<Buffer>;
2681
2662
  /**
2682
- * 'wait'-mode backpressure handler (Plan 05, CLIENT-07/CLIENT-11).
2663
+ * 'wait'-mode backpressure handler.
2683
2664
  *
2684
2665
  * Awaits one of three terminating signals, in order:
2685
2666
  * - `'drain'` event → re-enter `send()` (the gate will now pass).
2686
2667
  * - `ackTimeoutMs` elapses → reject with `MllpTimeoutError`.
2687
- * - Caller's `signal` aborts → reject with `AbortError` (B-06). Cleanup
2668
+ * - Caller's `signal` aborts → reject with `AbortError`. Cleanup
2688
2669
  * removes the drain listener AND the abort listener AND clears the
2689
2670
  * timer to prevent leaks.
2690
2671
  */
@@ -2732,7 +2713,7 @@ declare class MllpClient extends EventEmitter {
2732
2713
  */
2733
2714
  destroy(reason?: Error): void;
2734
2715
  /**
2735
- * Returns a JSON-serializable observability snapshot (OBS-01, D-26).
2716
+ * Returns a JSON-serializable observability snapshot.
2736
2717
  *
2737
2718
  * All fields are plain values, no Buffers, no class instances, no Maps,
2738
2719
  * no circular refs. Safe to `JSON.stringify` directly.
@@ -2769,15 +2750,15 @@ declare class MllpClient extends EventEmitter {
2769
2750
  *
2770
2751
  * const client = createClient({ host: 'localhost', port: 2575 });
2771
2752
  * await client.connect();
2772
- * // PLAN-02 will add: const ack = await client.send(payloadBuffer);
2753
+ * const ack = await client.send(payloadBuffer);
2773
2754
  * await client.close();
2774
2755
  * ```
2775
2756
  */
2776
2757
  declare function createClient(opts: ClientOptions): MllpClient;
2777
2758
  /**
2778
- * Options for {@link createStarterClient} (PLAN-06, CLIENT-10).
2759
+ * Options for {@link createStarterClient}.
2779
2760
  *
2780
- * The starter applies opinionated D-22 defaults on top of `ClientOptions`,
2761
+ * The starter applies opinionated defaults on top of `ClientOptions`,
2781
2762
  * so every override here is optional except `host` + `port`. The
2782
2763
  * starter-specific addition is `handleSignals` (mirrors `createStarterServer`).
2783
2764
  *
@@ -2814,31 +2795,30 @@ interface StarterClientOptions {
2814
2795
  readonly onBackpressure?: "reject" | "wait";
2815
2796
  /** Override default `true` (auto-reconnect on transient errors). */
2816
2797
  readonly autoReconnect?: boolean;
2817
- /** Custom reconnect-backoff hook (CLIENT-12). */
2798
+ /** Custom reconnect-backoff hook. */
2818
2799
  readonly retryStrategy?: RetryStrategy;
2819
2800
  /** Drain timeout for `close()` (default `30_000`). */
2820
2801
  readonly drainTimeoutMs?: number;
2821
2802
  /** FrameReader options (passthrough). */
2822
2803
  readonly framing?: ClientOptions["framing"];
2823
- /** TCP keepalive interval ms (CLIENT-08). */
2804
+ /** TCP keepalive interval ms. */
2824
2805
  readonly keepaliveIntervalMs?: number;
2825
- /** Application-idle dead-peer timeout ms (CLIENT-08). */
2806
+ /** Application-idle dead-peer timeout ms. */
2826
2807
  readonly deadPeerTimeoutMs?: number;
2827
- /** Enable TLS (MLLPS) for this connection (Phase 8). Passthrough to `ClientOptions.tls`. */
2808
+ /** Enable TLS (MLLPS) for this connection. Passthrough to `ClientOptions.tls`. */
2828
2809
  readonly tls?: TlsOptions | true;
2829
2810
  /**
2830
2811
  * Register process SIGTERM/SIGINT handlers that close the client. Default
2831
- * `false` (D-22). When `true`, SIGTERM/SIGINT both call `client.close()`
2832
- * and exit the process. Handlers self-deregister on `'close'` (T-05-06-01).
2812
+ * `false`. When `true`, SIGTERM/SIGINT both call `client.close()`
2813
+ * and exit the process. Handlers self-deregister on `'close'`.
2833
2814
  */
2834
2815
  readonly handleSignals?: boolean;
2835
2816
  }
2836
2817
  /**
2837
- * Three-line MLLP client with batteries-included defaults (PLAN-06,
2838
- * CLIENT-10, D-22). The returned client is already CONNECTED, `connect()`
2839
- * has been awaited.
2818
+ * Three-line MLLP client with batteries-included defaults. The returned
2819
+ * client is already CONNECTED, `connect()` has been awaited.
2840
2820
  *
2841
- * D-22 defaults:
2821
+ * Defaults:
2842
2822
  * - `autoReconnect: true`
2843
2823
  * - `ackTimeoutMs: 30_000`
2844
2824
  * - `correlateByControlId: false` (FIFO mode, simplest mental model)
@@ -2865,9 +2845,9 @@ declare function createStarterClient(opts: StarterClientOptions): Promise<MllpCl
2865
2845
  * MLLP Client typed errors and classifiers.
2866
2846
  *
2867
2847
  * Exports:
2868
- * - `MllpTimeoutError` (PLAN-02), ACK timeout (ERR-02)
2869
- * - `MllpBackpressureError`, high-water mark exceeded (ERR-04, plan 05)
2870
- * - `isTransientConnectionError` (PLAN-04), transient/permanent classifier (CLIENT-18)
2848
+ * - `MllpTimeoutError`, ACK timeout
2849
+ * - `MllpBackpressureError`, high-water mark exceeded
2850
+ * - `isTransientConnectionError`, transient/permanent classifier
2871
2851
  *
2872
2852
  * Re-exported from `src/client/index.ts` and `src/index.ts`.
2873
2853
  *
@@ -2875,11 +2855,10 @@ declare function createStarterClient(opts: StarterClientOptions): Promise<MllpCl
2875
2855
  */
2876
2856
  /**
2877
2857
  * Thrown (or rejects the `send()` promise) when an ACK does not arrive within
2878
- * the configured `ackTimeoutMs` (ERR-02).
2858
+ * the configured `ackTimeoutMs`.
2879
2859
  *
2880
2860
  * The timeout clock starts at the underlying `write()` flush callback, NOT
2881
- * at the `send()` call, pre-flush queue time is not charged to the peer
2882
- * (CLIENT-04).
2861
+ * at the `send()` call, pre-flush queue time is not charged to the peer.
2883
2862
  *
2884
2863
  * @example
2885
2864
  * ```typescript
@@ -2917,7 +2896,7 @@ declare class MllpTimeoutError extends Error {
2917
2896
  * failure (as opposed to some other TLS handshake failure), untrusted chain,
2918
2897
  * expired/not-yet-valid certificate, hostname mismatch, revocation, etc.
2919
2898
  *
2920
- * Used by `MllpClient` (Phase 8) to classify a TLS connect failure's
2899
+ * Used by `MllpClient` to classify a TLS connect failure's
2921
2900
  * `connectionCause` as `'tls-verify'` (this set) vs `'tls-handshake'`
2922
2901
  * (everything else observed before `'secureConnect'`). Exported so callers
2923
2902
  * can apply the same classification to their own error handling.
@@ -2933,7 +2912,7 @@ declare class MllpTimeoutError extends Error {
2933
2912
  declare function isTlsVerificationErrorCode(code: string): boolean;
2934
2913
  /**
2935
2914
  * Detects **TLS-protocol-shaped** errors, failures of the TLS protocol
2936
- * itself, as opposed to plain TCP-level network failures (Phase 8).
2915
+ * itself, as opposed to plain TCP-level network failures.
2937
2916
  *
2938
2917
  * Apply this only to errors raised on a **TLS** connection; `MllpClient`
2939
2918
  * does exactly that (the predicate is consulted only when `ClientOptions.tls`
@@ -2986,27 +2965,27 @@ declare function isTlsProtocolError(err: unknown): boolean;
2986
2965
  * Classifies a connection error as transient (eligible for auto-reconnect)
2987
2966
  * or permanent (halts auto-reconnect, transitions to CLOSED).
2988
2967
  *
2989
- * Used internally by `MllpClient` BEFORE invoking `retryStrategy` (Composition A
2990
- * see `RetryContext.classifiedAs`). Re-exported so callers can implement
2968
+ * Used internally by `MllpClient` BEFORE invoking `retryStrategy`
2969
+ * (see `RetryContext.classifiedAs`). Re-exported so callers can implement
2991
2970
  * their own retry policies.
2992
2971
  *
2993
- * Classification table (CLIENT-18, D-16):
2972
+ * Classification table:
2994
2973
  * - `ENOTFOUND`, `EACCES` → **permanent** (`false`)
2995
2974
  * - `ECONNREFUSED`, `ECONNRESET`, `ETIMEDOUT`, `EHOSTUNREACH`,
2996
2975
  * `ENETUNREACH`, `EPIPE` → **transient** (`true`)
2997
2976
  * - `CERT_*` and `UNABLE_TO_VERIFY_LEAF_SIGNATURE` /
2998
2977
  * `DEPTH_ZERO_SELF_SIGNED_CERT` / `SELF_SIGNED_CERT_IN_CHAIN`
2999
2978
  * (any {@link isTlsVerificationErrorCode} code) → **permanent** (`false`),
3000
- * never auto-reconnect-loop into a misconfigured or MITM'd endpoint (Phase 8).
2979
+ * never auto-reconnect-loop into a misconfigured or MITM'd endpoint.
3001
2980
  * - `ERR_SSL_*` (Node TLS alert codes) → **permanent** (`false`), a TLS
3002
2981
  * protocol failure such as a `clientAuth: 'MUST'` server rejecting the
3003
- * client certificate recurs on every attempt (Phase 8). On TLS-configured
2982
+ * client certificate recurs on every attempt. On TLS-configured
3004
2983
  * connections `MllpClient` additionally consults {@link isTlsProtocolError},
3005
2984
  * which also catches `EPROTO`/alert-bearing OpenSSL errors that this
3006
2985
  * generic classifier (which cannot know the connection was TLS) leaves
3007
2986
  * transient.
3008
2987
  * - `MLLP_*` (any {@link MllpFramingError} code, a fatal decoder throw, surfaced with
3009
- * `connectionCause: 'framing-fatal'`) → **permanent** (`false`) (MLLP-10). The peer is not
2988
+ * `connectionCause: 'framing-fatal'`) → **permanent** (`false`). The peer is not
3010
2989
  * speaking MLLP, an HTTP probe, a health check, a wrong-port misconfiguration, or is emitting
3011
2990
  * frames past `maxFrameSizeBytes`. Every reconnect meets the same bytes, so retrying is an
3012
2991
  * unbounded storm against a peer that is already misconfigured. If a peer's quirk is *expected*,
@@ -3030,11 +3009,10 @@ declare function isTlsProtocolError(err: unknown): boolean;
3030
3009
  declare function isTransientConnectionError(err: unknown): boolean;
3031
3010
  /**
3032
3011
  * Thrown (or rejects the `send()` promise) when the in-flight queue exceeds
3033
- * the configured high-water mark and `onBackpressure: 'reject'` is set
3034
- * (CLIENT-07, ERR-04).
3012
+ * the configured high-water mark and `onBackpressure: 'reject'` is set.
3035
3013
  *
3036
3014
  * `highWaterMark` accepts a count cap, a byte cap, or both, when both are
3037
- * present, the stricter-of-two trigger wins (D-23).
3015
+ * present, the stricter-of-two trigger wins.
3038
3016
  *
3039
3017
  * @example
3040
3018
  * ```typescript
@@ -3057,7 +3035,7 @@ declare class MllpBackpressureError extends Error {
3057
3035
  readonly queueDepth: number;
3058
3036
  /** Total bytes of in-flight + queued frames at the moment of rejection. */
3059
3037
  readonly queueBytes: number;
3060
- /** The high-water-mark configuration that was triggered (D-23). */
3038
+ /** The high-water-mark configuration that was triggered. */
3061
3039
  readonly highWaterMark: {
3062
3040
  readonly count?: number;
3063
3041
  readonly bytes?: number;