cross-tab-worker-databus 0.21.41 → 0.21.43

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cluster.d.ts","sourceRoot":"","sources":["../../src/core/cluster.ts"],"names":[],"mappings":"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"}
@@ -73,10 +73,36 @@ export declare class DedupManager {
73
73
  private readonly seenMessageIds;
74
74
  private sweepTimer;
75
75
  private windowStartedAt;
76
+ /** The most recent finite reading of `now`, and the fallback for a broken one. */
77
+ private lastFiniteNow;
76
78
  private windowAccepted;
77
79
  private suppressed;
78
80
  private accepted;
79
81
  constructor(options: DedupManagerOptions);
82
+ /**
83
+ * The injected clock, normalized.
84
+ *
85
+ * `dedup.now` is a public option and a non-wall-clock host is exactly the case it
86
+ * exists for — one whose reading can be *missing* rather than merely unusual. Every
87
+ * comparison this class makes is arithmetic on a timestamp, so a single non-finite
88
+ * reading does not degrade one field: `now - timestamp > ttlMs` becomes
89
+ * `NaN > ttlMs` (false, so nothing expires), the adaptive window's
90
+ * `elapsed >= ADAPTIVE_WINDOW_MS` never fires, and `getStats().ttlMs` reports
91
+ * `NaN` — which `JSON.stringify` turns into `null`, so a health summary or a
92
+ * diagnostics log would carry a null where a duration belongs. Measured on the
93
+ * pre-fix class: `getStats().ttlMs` → `NaN`, serialized → `null`, and an id
94
+ * stayed suppressed for as long as it stayed in the map.
95
+ *
96
+ * Holding the last finite reading is the degradation that changes least: time
97
+ * stands still, expiry pauses, and the adaptive window keeps the value it last
98
+ * computed. Substituting `Date.now()` would be worse — it silently mixes two
99
+ * clocks — and zeroing would expire the whole map on the next call. This is the
100
+ * same class of guard `trace.ts` carries on its own public clock, and that
101
+ * `websocket.ts` and `replay-manager.ts` apply to their numeric options; it is one
102
+ * helper rather than a condition per site because the broken input is the *clock*,
103
+ * not any particular comparison.
104
+ */
105
+ private nowMs;
80
106
  /** True when a publication carrying `messageId` was already seen. Records the
81
107
  * ID and updates counters/trace on acceptance. Disabled or ID-less messages
82
108
  * always pass through. */
@@ -1 +1 @@
1
- {"version":3,"file":"dedup-manager.d.ts","sourceRoot":"","sources":["../../src/core/dedup-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC;wBACoB;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9D,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,sEAAsE;IACtE,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,8DAA8D;IAC9D,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAUD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAK;gBAET,OAAO,EAAE,mBAAmB;IAWxC;;8BAE0B;IAC1B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAmCtD;8EAC0E;IAC1E,KAAK,IAAI,IAAI;IAKb,sCAAsC;IACtC,IAAI,IAAI,IAAI;IAKZ,+EAA+E;IAC/E,QAAQ,IAAI,iBAAiB;IAU7B,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAQb,oEAAoE;IACpE,OAAO,CAAC,YAAY;IAOpB;;;mCAG+B;IAC/B,OAAO,CAAC,UAAU;CAanB"}
1
+ {"version":3,"file":"dedup-manager.d.ts","sourceRoot":"","sources":["../../src/core/dedup-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGpD,kFAAkF;AAClF,MAAM,WAAW,mBAAmB;IAClC;wBACoB;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,yEAAyE;IACzE,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAChD;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9D,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,sEAAsE;IACtE,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,8DAA8D;IAC9D,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAUD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+C;IAC9E,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,eAAe,CAAK;IAC5B,kFAAkF;IAClF,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAK;gBAET,OAAO,EAAE,mBAAmB;IAexC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,CAAC,KAAK;IASb;;8BAE0B;IAC1B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAmCtD;8EAC0E;IAC1E,KAAK,IAAI,IAAI;IAKb,sCAAsC;IACtC,IAAI,IAAI,IAAI;IAKZ,+EAA+E;IAC/E,QAAQ,IAAI,iBAAiB;IAU7B,wDAAwD;IACxD,KAAK,IAAI,IAAI;IAQb,oEAAoE;IACpE,OAAO,CAAC,YAAY;IAOpB;;;mCAG+B;IAC/B,OAAO,CAAC,UAAU;CAanB"}
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  selectRebalanceTarget,
21
21
  selectWorkerBackend,
22
22
  topicMatchesPattern
23
- } from "./chunk-37U5AL4M.js";
23
+ } from "./chunk-NTMMSR4W.js";
24
24
  import {
25
25
  DEFAULT_STORAGE_PREFIX,
26
26
  PRUNE_STRATEGY,
package/docs/api.md CHANGED
@@ -133,7 +133,7 @@ Calling `publish()` while `stop()` is still settling reports through `onError` a
133
133
 
134
134
  A publication issued after a runtime transport `error` is held behind the recovery gate and sent once the transport is ready again, so it is never written to the connection that just failed. If the recovery budget is exhausted or the wait is superseded by `stop()` / page hide, the publication is dropped rather than deferred indefinitely (page suspension keeps its documented drop-without-defer semantics). A clean `disconnected` status does not schedule a background DataBus reopen, but it no longer swallows later operations either: a `subscribe()` / `publish()` issued after the close demands one on-demand reopen, is held until the replacement connects, and then flushes. Call `start()` (or send an operation) to reopen explicitly.
135
135
 
136
- Incoming messages may include a caller/server supplied `messageId`. Enable bounded duplicate suppression with `dedup: { maxEntries, ttlMs }`; repeated IDs within the bounded per-bus window are ignored. This is disabled by default and is best-effort: it does not provide an end-to-end at-least-once or exactly-once server guarantee. One accepted transport publication is fanned out once and dispatches at most once per matching local handler, while the transport/server may still redeliver or lose publications and a disconnected or suspended tab can miss the cross-tab event. Tests and hosts with a custom time source may provide `dedup.now`. A full `stop()` clears the remembered ID window; a later `start()` begins a fresh dedup session.
136
+ Incoming messages may include a caller/server supplied `messageId`. Enable bounded duplicate suppression with `dedup: { maxEntries, ttlMs }`; repeated IDs within the bounded per-bus window are ignored. This is disabled by default and is best-effort: it does not provide an end-to-end at-least-once or exactly-once server guarantee. One accepted transport publication is fanned out once and dispatches at most once per matching local handler, while the transport/server may still redeliver or lose publications and a disconnected or suspended tab can miss the cross-tab event. Tests and hosts with a custom time source may provide `dedup.now`; a reading that is not a finite number is held at the last finite one rather than propagated, so a host whose clock can be *missing* rather than merely unusual degrades to time standing still — expiry pauses and the adaptive window keeps its last value — instead of reporting `NaN` in `getDedupStats()` (which serializes as `null`) and expiring nothing. A full `stop()` clears the remembered ID window; a later `start()` begins a fresh dedup session.
137
137
 
138
138
  When supplied, `options.messageId` and `options.timestamp` are propagated through cross-tab routing, Worker boundaries, and supported transports. The server must echo or otherwise preserve them for inbound deduplication and replay retention.
139
139
 
@@ -101,7 +101,7 @@ Terms are explained in plain language; the code and the rest of this document us
101
101
 
102
102
  ## Storage Structure
103
103
 
104
- All keys are isolated by `createOpaqueKey(clusterKey)`. Topics are also stored as 128-bit opaque keys.
104
+ All `localStorage` keys are isolated by `createOpaqueKey(clusterKey)`. Topics are also stored as 128-bit opaque keys. (IndexedDB is not part of this namespace — see the `replay.persistence` note below.)
105
105
 
106
106
  BroadcastChannel messages carry topic names, event types, and publication payloads in plaintext. Only the channel name (derived from `clusterKey`) is hashed. If topic names are sensitive, avoid including them as part of the plaintext payload, or use an end-to-end encryption layer on top of the data bus.
107
107
 
@@ -169,7 +169,14 @@ The second row is what makes ownership authorization meaningful. `topicKey` is a
169
169
  `topic`, so every frame this library builds has the two agreeing; a pair that disagrees is therefore a
170
170
  substitution, not a variant — and because ownership is authorized by the route stored under `topicKey`
171
171
  while the transport subscription is named by `topic`, an unchecked mismatch lets a frame borrow one
172
- channel's authorization to name another. The durable route record stores only `topicKey`, never the
172
+ channel's authorization to name another.
173
+
174
+ The comparison is unconditional, and **a frame that carries no `topicKey` at all is a disagreement of
175
+ the same kind**: the field is required on this message variant, `createOpaqueKey(topic)` is 32 hex
176
+ characters, and `undefined` is not one of them — so a missing field is dropped here rather than read as
177
+ a legacy shape. That is worth stating because the alternative reading is the natural one (the check
178
+ rejects a *mismatch*, so a frame with nothing to mismatch is presumably tolerated), and it was the
179
+ reason one reader of this document kept a guard that let such a frame through until 0.21.42. The durable route record stores only `topicKey`, never the
173
180
  plaintext, so the key → name mapping exists only in memory and cannot be injected through the
174
181
  coordination records. The storage-event fallback channel is the one path where a frame — and with it
175
182
  a key/plaintext pair — does arrive through localStorage; the pairing rule is what makes a frame
@@ -188,8 +195,9 @@ only forwarded into `transport.publish()`, where the receiving side discards a n
188
195
  non-finite timestamp when it parses the publication.
189
196
 
190
197
  **For a non-JS peer or a custom environment:** derive `topicKey` from the topic with
191
- `createOpaqueKey`, never send a batch with zero items, and expect a frame to be ignored without any
192
- response if the pair disagrees.
198
+ `createOpaqueKey` and **always send it** (there is no tolerated shape without it), never send a batch
199
+ with zero items, and expect a frame to be ignored without any response if the pair disagrees or the key
200
+ is missing.
193
201
 
194
202
  ### How `topic`, `topicKey`, `tabId`, `workerId`, and BroadcastChannel relate
195
203
 
@@ -242,7 +250,7 @@ Eviction is FIFO (insertion order, Map iteration order). When the cache exceeds
242
250
 
243
251
  **Opaque key collision.** `createOpaqueKey` is a non-cryptographic 128-bit hash. The birthday collision bound (~2⁶⁴ for 50% probability) is far beyond the number of topics a single cluster handles (thousands at most). Similarly, `clusterKey` is hashed via `createOpaqueKey` to derive the storage prefix and BroadcastChannel name. In practice, `clusterKey` is always a connection URL or a developer-controlled namespace — naturally unique, so cross-cluster collision is not a concern.
244
252
 
245
- **`clusterKey` isolation.** The `clusterKey` defines the cluster boundary. Two DataBus instances with different `clusterKey` values — even in the same origin — operate on completely isolated storage namespaces and BroadcastChannel names, even if they happen to use the same transport connection. This is how different logical clusters (e.g. market data vs. notifications) coexist without cross-talk.
253
+ **`clusterKey` isolation.** The `clusterKey` defines the cluster boundary. Two DataBus instances with different `clusterKey` values — even in the same origin — operate on completely isolated `localStorage` namespaces and BroadcastChannel names, even if they happen to use the same transport connection. This is how different logical clusters (e.g. market data vs. notifications) coexist without cross-talk. The one surface outside that boundary is the `replay.persistence` opt-in: its IndexedDB object store is keyed by the plaintext Topic and its database name defaults to the storage prefix, so it is not partitioned by `clusterKey` at all — pass `dbName` per cluster when an application runs more than one. See the Storage Data Boundaries section in the configuration guide for the full enumeration.
246
254
 
247
255
  **`knownTopics` lifecycle.** The cache is populated, read, and cleaned at specific points:
248
256
 
@@ -273,7 +273,9 @@ Those records never hold:
273
273
  That is a boundary around *those keys*, not around browser storage in general. Two opt-ins put Topic plaintext and payloads into it:
274
274
 
275
275
  - `channelFallback: 'storage-event'` writes every coordination **frame** whole under `cross-tab-worker-databus:channel:*`, and a `CONTROL/PUBLISH` frame carries its Topic name and payload — so they sit in `localStorage` until the channel is closed, and indefinitely if the tab is killed first.
276
- - `replay.persistence` (e.g. `createIndexedDbReplayPersistence`) keeps replay history in IndexedDB in an object store keyed by the plaintext Topic, with the payloads in its rows.
276
+ - `replay.persistence` (e.g. `createIndexedDbReplayPersistence`) keeps replay history in IndexedDB in an object store keyed by the plaintext Topic, with the payloads in its rows. That store is keyed by the Topic and nothing else — its database name defaults to the package's storage prefix — so it is **not** scoped by `clusterKey` or by tab: two clusters running in one origin read each other's rows for any Topic they share. Pass `dbName` per cluster when an application runs more than one.
277
+
278
+ Those two are the complete list, and it is checked rather than asserted: every durable write in `src/` is enumerated in `tests/storage-writers.test.ts`, and a new one — or a new row that carries a Topic without naming one of these two options — fails the suite.
277
279
 
278
280
  Note: BroadcastChannel coordination messages carry topic names, event types, and publication payloads in plaintext (in memory only, unless the fallback above is what is carrying them). Only localStorage metadata is hashed via `createOpaqueKey()`.
279
281
 
package/docs/roadmap.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Roadmap
2
2
 
3
- 0.21.40 was released on September 25, 2026. The project is intentionally continuing through reliability-focused releases before a 1.0.0 stability freeze.
3
+ 0.21.42 was released on September 26, 2026. The project is intentionally continuing through reliability-focused releases before a 1.0.0 stability freeze.
4
+
5
+ ## 0.21.43 delivered scope
6
+
7
+ - **A public clock could report `NaN` into the health summary.** `dedup.now` is documented for "non-wall-clock hosts", and every comparison in the dedup manager is arithmetic on a timestamp — so one non-finite reading did not degrade one field: the adaptive window never reset, nothing expired on the hot path or in the sweep, and `getDedupStats().ttlMs` reported `NaN`, which `JSON.stringify` writes as `null`. Measured on the pre-fix class. The manager now holds the last finite reading, and the guard sits at the clock rather than at each comparison — the shape this repository already uses for the same class of input in `trace.ts`, `websocket.ts` and `replay-manager.ts`.
8
+ - **Two shipped copies of a retired claim are corrected where they are widest.** The architecture guide carried the per-`clusterKey` storage isolation claim in a *dedicated* section and as an absolute above its key listing; both now name the `replay.persistence` store as outside that boundary, since its IndexedDB object store is keyed by the plaintext Topic and its database name never sees the cluster key. The protocol section's description of the key/plaintext pairing now matches what `0.21.42` enforces: unconditional, with a missing field being a disagreement of the same kind. Both languages.
9
+
10
+ ## 0.21.42 delivered scope
11
+
12
+ - **A guard written to tolerate a missing field it never had to tolerate.** `AGENTS.md` claimed both point-to-point handlers carrying the `topicKey`/`topic` pair enforce it; re-auditing the claim rather than the code showed they disagreed, because `handleControlMessage` guarded the comparison with `message.topicKey !== undefined &&` while `handleRouteReleasedMessage` never carried that clause. The tolerance had no referent to protect — the field has been required since the initial commit, so no released version ever omitted it, and the clause arrived in the same commit as the check — and its only reachable traffic was a forger, who could make `getSnapshot().assignedTopics` report a topic the tab never subscribed until the next reconcile swept it. Measured consequence: no durable ownership minted, nothing written to storage, hence patch. The general form is now written down beside the protocol: a tolerance for a missing field is a claim about which peers exist, so read the field's history in the protocol type before writing one.
13
+ - **The storage-plaintext invariant was enforced on keys by accident and on values by nothing.** Three mutations, measured: a route record carrying a `topic` field beside its `topicKey` failed 1 test in 969 (a new sweep arm, alone), while a plaintext-bearing key also tripped two pre-existing cases that are about something else. The sweep now checks keys *and* values after every step rather than only on the quiesced end state, and `tests/storage-writers.test.ts` enumerates every durable write in `src/`, so the two documented opt-ins are a checked list rather than a claim — its topic half exists because the obvious word test was measured passing a leak that travelled through a variable named `topicKey`.
4
14
 
5
15
  ## 0.21.41 delivered scope
6
16
 
package/docs/zh/api.md CHANGED
@@ -133,7 +133,7 @@ publish(
133
133
 
134
134
  运行期 transport 上报 `error` 后发起的发布同样会挂在恢复门之后,等 transport 重新 ready 再发送,因此不会被写进刚刚失败的连接。若恢复预算耗尽,或等待被 `stop()` / 页面隐藏取代,该发布会按文档丢弃而不是无限期延迟(页面挂起仍保持「不延迟、直接丢弃」语义)。干净的 `disconnected` 不会触发后台 DataBus 自动重开,但也不会再吞掉后续操作:干净关闭后发起的 `subscribe()` / `publish()` 会触发一次按需重开,先挂起等待替代连接就绪,随后再 flush。可显式调用 `start()`(或直接发起操作)来重开。
135
135
 
136
- 入站消息可携带调用方/服务端提供的 `messageId`。可通过 `dedup: { maxEntries, ttlMs }` 启用有界重复抑制;每个 bus 实例只会忽略其窗口内的重复 ID。该能力默认关闭且属于尽力而为:它不提供端到端的 at-least-once 或 exactly-once 服务端保证。每条被接受的 transport publication 只会扇出一次,每个匹配的本地 handler 至多分发一次;但 transport/服务端仍可能重复投递或丢失,断连或挂起中的 Tab 也可能错过跨 Tab 事件。测试和自定义时钟宿主可传入 `dedup.now`。完整 `stop()` 会清空已记住的 ID 窗口;之后的 `start()` 会开启全新的 dedup 会话。
136
+ 入站消息可携带调用方/服务端提供的 `messageId`。可通过 `dedup: { maxEntries, ttlMs }` 启用有界重复抑制;每个 bus 实例只会忽略其窗口内的重复 ID。该能力默认关闭且属于尽力而为:它不提供端到端的 at-least-once 或 exactly-once 服务端保证。每条被接受的 transport publication 只会扇出一次,每个匹配的本地 handler 至多分发一次;但 transport/服务端仍可能重复投递或丢失,断连或挂起中的 Tab 也可能错过跨 Tab 事件。测试和自定义时钟宿主可传入 `dedup.now`;读数不是有限数值时会保持在最近一次有限读数上而不是被传播下去,因此对于时钟可能*缺失*(而不只是数值异常)的主机,退化结果是时间静止——过期暂停、自适应窗口保留上次的值——而不是在 `getDedupStats()` 里报出 `NaN`(序列化后是 `null`)且什么都不过期。完整 `stop()` 会清空已记住的 ID 窗口;之后的 `start()` 会开启全新的 dedup 会话。
137
137
 
138
138
  传入 `options.messageId` 和 `options.timestamp` 后,元数据会穿过跨 Tab 路由、Worker 边界和支持的 transport。服务端必须回显或以其他方式保留它们,入站去重和 replay retention 才能使用。
139
139
 
@@ -170,7 +170,7 @@ clearReplay(): Promise<void>
170
170
 
171
171
  清空内存 replay 缓冲,并调用持久化适配器可选的 `clear()`。适合留存策略、退出登录或租户切换;普通 `stop()` 仍会保留 durable history。
172
172
 
173
- `clearReplayTopic(topic)` 只清理一个精确 topic。`getDedupStats()` 返回 `enabled`、`tracked`、`accepted`、`suppressed` 四项有界统计,配置了 `dedup.adaptiveTtl` 时还会多一个当前 `ttlMs`;`resetDedup()` 清除已记忆 ID 和计数,不改变 dedup 配置。为测试或非墙上时钟宿主,可额外提供 `dedup.now`。完整 `stop()` 会清空已记忆的 ID 窗口,之后 `start()` 会开启新的 dedup 会话。
173
+ `clearReplayTopic(topic)` 只清理一个精确 topic。`getDedupStats()` 返回 `enabled`、`tracked`、`accepted`、`suppressed` 四项有界统计,配置了 `dedup.adaptiveTtl` 时还会多一个当前 `ttlMs`;`resetDedup()` 清除已记忆 ID 和计数,不改变 dedup 配置。为测试或非墙上时钟宿主,可额外提供 `dedup.now`;读数不是有限数值时保持在最近一次有限读数上,因此时钟可能缺失的主机退化为时间静止,而不是让统计里出现 `NaN`。完整 `stop()` 会清空已记忆的 ID 窗口,之后 `start()` 会开启新的 dedup 会话。
174
174
 
175
175
  `clearReplayBefore(timestamp)` 按毫秒时间戳清理带显式 producer timestamp 且早于 cutoff 的记录;实现可选 `clearBefore()` 的持久化适配器由它 `await`,这一路还经过带退避的重试,因此清理不会在同一个任务内同步完成。没有 producer timestamp 的 legacy 消息会为兼容性保留。transport 未提供时间戳时,系统仍会补充 bus timestamp,但该时间戳不会被当作 producer metadata 用于 retention 清理。
176
176
 
@@ -91,7 +91,7 @@ graph TB
91
91
 
92
92
  ## 存储结构
93
93
 
94
- 所有 key 都通过 `createOpaqueKey(clusterKey)` 隔离。Topic 也以 128-bit 不透明 key 存储。
94
+ 所有 `localStorage` key 都通过 `createOpaqueKey(clusterKey)` 隔离。Topic 也以 128-bit 不透明 key 存储。(IndexedDB 不属于这个命名空间——见下面的 `replay.persistence` 说明。)
95
95
 
96
96
  BroadcastChannel 消息以明文传输 Topic 名称、事件类型和 publication payload。只有通道名称(由 `clusterKey` 派生)会被哈希处理。如果 Topic 名称包含敏感信息,请避免将其包含在明文 payload 中,或在数据总线之上使用端到端加密层。
97
97
 
@@ -152,13 +152,15 @@ interface WorkerRoute {
152
152
  | `topicKey === createOpaqueKey(topic)` | `CONTROL`(任意 action)与 `ROUTE_RELEASED` | 帧被忽略 |
153
153
  | 携带 `items` 的 `CONTROL/PUBLISH` 帧必须给出非空**数组** | `CONTROL/PUBLISH` | 帧被忽略 |
154
154
 
155
- 第二行是所有权的授权前提。`topicKey` 是 `topic` 的纯函数,所以本库构造的每个帧两者必然一致;不一致就是替换而非变体。由于所有权依据 `topicKey` 对应的持久路由判定,而传输层订阅的名字来自 `topic`,不校验就允许一帧借用某个频道的授权去命名另一个频道。持久路由记录只保存 `topicKey`、从不保存明文,因此 key → 明文的映射只存在于内存中,无法通过协调记录注入。storage-event 降级通道是唯一一帧"经由 localStorage 到达"的路径;配对规则的作用不变——其他租户写进这块存储的帧,和直接 post 进通道一样无效。
155
+ 第二行是所有权的授权前提。`topicKey` 是 `topic` 的纯函数,所以本库构造的每个帧两者必然一致;不一致就是替换而非变体。由于所有权依据 `topicKey` 对应的持久路由判定,而传输层订阅的名字来自 `topic`,不校验就允许一帧借用某个频道的授权去命名另一个频道。
156
+
157
+ 这个比较是无条件的,而且**完全不带 `topicKey` 的帧属于同一类“不一致”**:该字段在这个消息变体上是必填的,`createOpaqueKey(topic)` 是 32 个十六进制字符,而 `undefined` 不是其中之一——因此缺失的字段在这里被丢弃,而不是被当成某种遗留形状。之所以值得写明,是因为另一种读法才是自然的那一种(这项检查拒绝的是*不一致*,那么一个没有可比对象的帧大概是被容忍的),而这正是有读者据此保留了一处守卫的原因,它让这类帧一路通行直到 0.21.42。持久路由记录只保存 `topicKey`、从不保存明文,因此 key → 明文的映射只存在于内存中,无法通过协调记录注入。storage-event 降级通道是唯一一帧"经由 localStorage 到达"的路径;配对规则的作用不变——其他租户写进这块存储的帧,和直接 post 进通道一样无效。
156
158
 
157
159
  第三行存在是因为批量路径会迭代负载:只有 `length` 而没有迭代器的值会从消息监听器里抛出异常;可迭代的非数组(字符串)会被当成多个单字符条目,其 `data` 为 `undefined`,随后 owner 会以自己的会话把它们发布出去。
158
160
 
159
161
  有两处是**故意不校验**的。`EVENT` 帧只做形状校验(`eventType` 加一个含字符串 `topic` 的负载)并转发其余字段,因为投递仍要求本地存在该频道的订阅者,而这种宽容正是新旧 SDK 版本能共处一个集群的前提。批量条目内部的*内容*也不校验:`{ data: 任意} ` 就是合法条目的样子,而 `messageId` / `timestamp` 只会被转发给 `transport.publish()`——接收侧在解析发布数据时会丢弃非字符串 id 与非有限数值时间戳。
160
162
 
161
- **给非 JS 对端或自定义 environment 的约定:**用 `createOpaqueKey` 从 topic 推导 `topicKey`,不要发送零条目的批次,并预期不一致的帧会被忽略且没有任何响应。
163
+ **给非 JS 对端或自定义 environment 的约定:**用 `createOpaqueKey` 从 topic 推导 `topicKey`,并且**始终发送它**(不存在“缺少它”这一被容忍的形状),不要发送零条目的批次,并预期当这一对不一致、或 key 缺失时帧会被忽略且没有任何响应。
162
164
 
163
165
  ### `topic`、`topicKey`、`tabId`、`workerId` 与 BroadcastChannel 的关联
164
166
 
@@ -212,7 +214,7 @@ BroadcastChannel CONTROL
212
214
 
213
215
  **不透明 key 碰撞**。`createOpaqueKey` 是非密码学 128-bit 哈希。生日碰撞概率(50% 概率约需 2⁶⁴ 次尝试)远超单个集群处理的 topic 数量(最多几千个)。同样,`clusterKey` 也通过 `createOpaqueKey` 哈希来派生 storage 前缀和 BroadcastChannel 名称。实践中 `clusterKey` 通常是连接 URL 或开发者控制的命名空间,天然唯一,跨集群碰撞不是问题。
214
216
 
215
- **`clusterKey` 隔离边界**。`clusterKey` 定义了集群边界。两个使用不同 `clusterKey` 的 DataBus 实例——即使在同一 origin——也使用完全隔离的 storage 命名空间和 BroadcastChannel 名称,即使它们碰巧使用相同的 transport 连接。这就是不同逻辑集群(比如行情数据 vs 通知)共存而不互相干扰的方式。
217
+ **`clusterKey` 隔离边界**。`clusterKey` 定义了集群边界。两个使用不同 `clusterKey` 的 DataBus 实例——即使在同一 origin——也使用完全隔离的 `localStorage` 命名空间和 BroadcastChannel 名称,即使它们碰巧使用相同的 transport 连接。这就是不同逻辑集群(比如行情数据 vs 通知)共存而不互相干扰的方式。唯一在这条边界之外的是 `replay.persistence` 这个开关:它的 IndexedDB object store 以 Topic 明文为 key,数据库名默认取 storage 前缀,因此完全不由 `clusterKey` 划分——当应用运行不止一个 cluster 时,请按 cluster 传入 `dbName`。完整的枚举见配置指南中的存储数据边界一节。
216
218
 
217
219
  **`knownTopics` 生命周期**。缓存在特定时机被写入、读取和清理:
218
220
 
@@ -266,7 +266,9 @@ Worker 模式下配置通过 `Worker` / `SharedWorker` 的 `postMessage` 发送
266
266
  这是对**这些键**的约束,不是对浏览器存储整体的约束。有两个开关会把 Topic 明文和 payload 写进去:
267
267
 
268
268
  - `channelFallback: 'storage-event'` 把每一帧协调消息整体写到 `cross-tab-worker-databus:channel:*` 之下,而一条 `CONTROL/PUBLISH` 帧同时携带它的 Topic 名称与 payload——因此这些数据会留在 `localStorage` 直到该 channel 关闭,若 tab 先退出则无限期保留。
269
- - `replay.persistence`(如 `createIndexedDbReplayPersistence`)把回放历史存在 IndexedDB 的一个 object store 里,该 store 以 Topic 明文为 key,payload 就在其中的行里。
269
+ - `replay.persistence`(如 `createIndexedDbReplayPersistence`)把回放历史存在 IndexedDB 的一个 object store 里,该 store 以 Topic 明文为 key,payload 就在其中的行里。这个 store 只以 Topic 为 key,别无其他——它的数据库名默认取本包的 storage 前缀——因此它**不**按 `clusterKey` 或 tab 划分作用域:同一 origin 下运行的两个 cluster 会读到彼此在共同 Topic 上的行。当应用运行不止一个 cluster 时,请按 cluster 传入 `dbName`。
270
+
271
+ 这两个就是全部,而且是核对出来的而非声称的:`src/` 中每一处持久化写入都在 `tests/storage-writers.test.ts` 里列成表,新增一处写入——或新增一行不归属于上面两个开关却携带 Topic 的记录——都会让测试失败。
270
272
 
271
273
  注意:BroadcastChannel 协调消息以明文传输 Topic 名称、事件类型和 publication payload(仅存在于内存中,除非承载它们的是上面那条降级通道)。只有 localStorage 元数据通过 `createOpaqueKey()` 哈希处理。
272
274
 
@@ -1,6 +1,16 @@
1
1
  # 路线图
2
2
 
3
- 0.21.40 已于 2026 年 9 月 25 日发布。项目会先持续完成可靠性发布,再进入 1.0.0 稳定性冻结。
3
+ 0.21.42 已于 2026 年 9 月 26 日发布。项目会先持续完成可靠性发布,再进入 1.0.0 稳定性冻结。
4
+
5
+ ## 0.21.43 已完成范围
6
+
7
+ - **一个公开时钟可能把 `NaN` 报进健康摘要。** `dedup.now` 是为“非墙上时钟宿主”准备的,而去重管理器里的每一次比较都是对时间戳做算术——于是一次非有限读数并不是让某个字段退化:自适应窗口永不重置,热路径和清扫都不过期,而 `getDedupStats().ttlMs` 报出 `NaN`,它被 `JSON.stringify` 写成 `null`。这是修复前实测到的。现在管理器会保持最近一次有限读数,守卫放在时钟处而不是每处比较——这正是本仓库对同类输入在 `trace.ts`、`websocket.ts` 和 `replay-manager.ts` 里已经采用的形状。
8
+ - **一条已退役的声称,在它出现得最显眼的两处被更正。** 架构指南把“按 `clusterKey` 隔离存储”的声称同时写在一个**专门小节**里和密钥清单上方的一句绝对表述里;两处现在都点名 `replay.persistence` 那个 store 在这条边界之外——它以 Topic 明文为 key,数据库名也从来看不到 cluster key。协议一节对 key/明文配对的描述现在与 `0.21.42` 实际强制的行为一致:比较是无条件的,字段缺失属于同一类“不一致”。两种语言。
9
+
10
+ ## 0.21.42 已完成范围
11
+
12
+ - **一处守卫为了容忍一个它从不需要容忍的缺失字段而写成。** `AGENTS.md` 声称携带 `topicKey`/`topic` 这一对字段的两个点对点处理器都强制执行该不变量;重新审计这个*声称*而不是代码,发现两者并不一致——`handleControlMessage` 把比较包在 `message.topicKey !== undefined &&` 后面,而 `handleRouteReleasedMessage` 从来没有这个子句。这个容忍没有可保护的对象:该字段自初始提交起就是必填的,因此没有任何已发布版本省略过它,而且这个子句与检查本身出现在同一次提交里。它唯一可达的流量来自伪造者,而伪造者能让 `getSnapshot().assignedTopics` 报出一个该 tab 从未订阅的 topic,直到下一次 reconcile 把它清掉。实测后果:没有产生落地的所有权,存储里也没有写入任何东西,因此是 patch。这条一般规律现在写在协议旁边:对缺失字段的容忍是在声称存在哪一类 peer,所以写之前先读协议类型里该字段的历史。
13
+ - **存储明文不变量此前在 key 上靠巧合被守住,在 value 上则完全没有约束。** 三个变异体的实测结果:一条在 `topicKey` 旁边带 `topic` 字段的 route 记录只让 969 个用例里的 1 个失败(新增的那条 sweep 支臂,独自失败),而一个携带明文的 key 还会额外触发两个与该主题无关的既有用例。现在 sweep 在每一步之后(而不只是在静默后的终态)同时检查 key *与* value,并且 `tests/storage-writers.test.ts` 把 `src/` 里每一处持久化写入都列了出来,于是那两个有文档的开关成了一份被核对过的清单——它关于 topic 的那一半之所以存在,是因为最直觉的词语检测被实测放过了一个经由名为 `topicKey` 的变量传播的泄漏。
4
14
 
5
15
  ## 0.21.41 已完成范围
6
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cross-tab-worker-databus",
3
- "version": "0.21.41",
3
+ "version": "0.21.43",
4
4
  "description": "Framework-agnostic cross-tab data bus with Dedicated/Shared Worker clustering and Centrifuge support.",
5
5
  "type": "module",
6
6
  "license": "MIT",