instar 1.3.548 → 1.3.549

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +112 -0
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +29 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CoherenceJournal.d.ts +1 -1
  8. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  9. package/dist/core/CoherenceJournal.js +23 -2
  10. package/dist/core/CoherenceJournal.js.map +1 -1
  11. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  12. package/dist/core/PostUpdateMigrator.js +27 -1
  13. package/dist/core/PostUpdateMigrator.js.map +1 -1
  14. package/dist/core/TopicOperatorReplicatedStore.d.ts +250 -0
  15. package/dist/core/TopicOperatorReplicatedStore.d.ts.map +1 -0
  16. package/dist/core/TopicOperatorReplicatedStore.js +413 -0
  17. package/dist/core/TopicOperatorReplicatedStore.js.map +1 -0
  18. package/dist/core/UserRegistryReplicatedStore.d.ts +287 -0
  19. package/dist/core/UserRegistryReplicatedStore.d.ts.map +1 -0
  20. package/dist/core/UserRegistryReplicatedStore.js +527 -0
  21. package/dist/core/UserRegistryReplicatedStore.js.map +1 -0
  22. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  23. package/dist/core/devGatedFeatures.js +10 -0
  24. package/dist/core/devGatedFeatures.js.map +1 -1
  25. package/dist/scaffold/templates.d.ts.map +1 -1
  26. package/dist/scaffold/templates.js +3 -1
  27. package/dist/scaffold/templates.js.map +1 -1
  28. package/dist/users/TopicOperatorStore.d.ts +24 -0
  29. package/dist/users/TopicOperatorStore.d.ts.map +1 -1
  30. package/dist/users/TopicOperatorStore.js +28 -0
  31. package/dist/users/TopicOperatorStore.js.map +1 -1
  32. package/dist/users/UserManager.d.ts +27 -0
  33. package/dist/users/UserManager.d.ts.map +1 -1
  34. package/dist/users/UserManager.js +44 -0
  35. package/dist/users/UserManager.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/data/builtin-manifest.json +19 -19
  38. package/src/scaffold/templates.ts +3 -1
  39. package/upgrades/1.3.549.md +36 -0
  40. package/upgrades/side-effects/multi-machine-replicated-store-ws26-user-topicop.md +123 -0
@@ -0,0 +1,123 @@
1
+ # Side-Effects Review — WS2.6 user-registry + topic-operator replicated stores (the last two memory-family PII kinds, dark)
2
+
3
+ **Version / slug:** `multi-machine-replicated-store-ws26-user-topicop`
4
+ **Date:** `2026-06-13`
5
+ **Author:** `Instar Agent (echo)`
6
+ **Second-pass reviewer:** `5-lens adversarial review (untrusted-replicated-operator / recordKey-identity / disclosure-min-PII-leak / tombstone-erasure / dark-ship-inertness) — verdict + named tests appended below`
7
+ **Parent principle:** Cross-Machine Coherence — One Agent, Robust Under Degraded Conditions
8
+
9
+ ## Summary of the change
10
+
11
+ WS2.6 adds the final two PII kinds to the WS2 memory family on the proven HLC
12
+ replicated-store foundation: `user-record` (the multi-user registry the `UserManager`
13
+ resolves an inbound message to) and `topic-operator-record` (which VERIFIED operator a
14
+ topic was bound to). Both are thin instantiations of the shipped WS2.3 relationships PII
15
+ template: discriminated-union-on-`op` schema (value + tombstone), strict type-clamp on
16
+ receive, disclosure-minimized projection, content/identity-surface `recordKey`, 64KB
17
+ per-entry cap with a named over-cap error, op:delete tombstone for offline-peer erasure,
18
+ HIGH-impact-at-replication / advisory-at-read. With these landed, the WS2 memory family
19
+ is COMPLETE (7 kinds: preferences, relationships, learnings, knowledge, evolution-actions,
20
+ user-registry, topic-operator; playbook deferred CMT-1416).
21
+
22
+ Both ship **DARK** behind `multiMachine.stateSync.userRegistry` and
23
+ `.topicOperator` (`enabled:false`, `dryRun:true` — the graduated dark→dryRun→live ladder).
24
+ Flag-off / single-machine = strict no-op; NO PII ever crosses a machine boundary while dark.
25
+
26
+ ## Decision-point inventory (the decided forks, baked in verbatim)
27
+
28
+ - **user-record recordKey** = `sha256(sorted channel-set "type:identifier" pairs)` — a user IS
29
+ their channel identifiers (same model as relationships, mirroring `UserManager.channelIndex`).
30
+ NEVER the local `userId` (the cross-machine-unstable id).
31
+ - **topic-operator recordKey** = `sha256(topicId + ":" + verified-uid)`. NEVER a content-name
32
+ (Know-Your-Principal: the binding is auth-sender-derived).
33
+ - **Impact tier**: BOTH HIGH@replication (append-both-and-flag on concurrent divergence) /
34
+ advisory@read (a replicated PII record is a hint, never the authoritative answer).
35
+ - **disclosure-min**: user-record strips the local `userId`; topic-operator projects exactly
36
+ `{platform, uid, names, boundAt}` (no internal `boundFrom`).
37
+ - **THE LOAD-BEARING INVARIANT (topic-operator)**: a replicated topic-operator record is
38
+ UNTRUSTED peer data — NEVER this machine's authoritative answer to "who is my verified
39
+ operator?". Only the LOCAL authenticated `TopicOperatorStore.setOperator` binds the principal.
40
+ The store exposes NO apply/set/establish path back into `TopicOperatorStore` by construction.
41
+
42
+ ## 1. Over-block
43
+ None. Both kinds ADD reach (replicated PII as advisory context) and never block a message, a
44
+ route, or a session. Flag-off / single-machine = strict no-op (named E2E + unit tests).
45
+
46
+ ## 2. Under-block (the real risk surface)
47
+ The inverse risk: replicated PII is materialized into a union read. Mitigations: (a) strict
48
+ type-clamp on receive (ISO-8601 dates, finite numbers, jailed slugs) makes markup
49
+ un-smuggleable through a render slot; (b) every foreign record renders inside a
50
+ `<replicated-untrusted-data origin="…">` envelope; (c) the topic-operator foreign render
51
+ EXPLICITLY states the record is NOT the verified operator and cannot establish/override one;
52
+ (d) identity RESOLUTION of an inbound principal stays LOCAL-ONLY for user-record (the local
53
+ channel index always wins); (e) the topic-operator store has no apply path, so a replicated
54
+ record can never reach `getOperator()` authority. Accepted residual: a compromised
55
+ same-operator peer could inject advisory context text, but it cannot escalate to principal
56
+ authority and the blast radius is one operator's own pool — recorded as a known bound.
57
+
58
+ ## 3. Level-of-abstraction fit
59
+ The two `*ReplicatedStore.ts` modules are PURE logic (no fs, no Date, no network) — schema +
60
+ projection + recordKey + merge + render, unit-testable in isolation. The wiring sits in
61
+ server.ts (kind registration + union reader) and the manager seams (`UserManager.persistUsers`/
62
+ `removeUser`, `TopicOperatorStore.setOperator`) exactly where the WS2.2–2.5 siblings sit. No
63
+ new transport, no new auth, no new tick.
64
+
65
+ ## 4. Signal vs authority compliance
66
+ Fully signal-only. Neither kind gates or rewrites anything. The user-registry merged read is a
67
+ HINT (inbound resolution stays local-authoritative); the topic-operator merged read is advisory
68
+ context (the principal stays local-authoritative). The mesh path is the existing read/observe
69
+ replicated-store substrate — adds reach, never authority; the receiver type-clamps + envelopes.
70
+
71
+ ## 5. Interactions
72
+ - Rides the existing `ReplicatedKindRegistry` + dual-registry (`JOURNAL_KINDS`) + union reader +
73
+ conflict/rollback substrate (no new machinery).
74
+ - Two new `enabled:false` ConfigDefaults paths shift the dark-gate EXPECTED line-map by +29;
75
+ hand-edited (regeneration forbidden) + two new attributed entries added.
76
+ - Coexists with the WS2.1–2.5 siblings (same `multiMachine.stateSync.*` block, independent flags).
77
+ - The maintainer's WS5.2 credential-repointing track was NOT touched (separate lane).
78
+
79
+ ## 6. External surfaces
80
+ No new HTTP routes. The kinds register onto the shared registry and ride the existing
81
+ `/state/*` conflict/quarantine routes (already alive). Emission/serve/pull stay dark behind the
82
+ two new flags. The journal-backed emitter is wired at the manager seams but only attached when
83
+ the flag is on (a later rollout stage, mirroring the siblings).
84
+
85
+ ## 7. Multi-machine posture (Cross-Machine Coherence) + Phase C
86
+ - **Per-machine emission; N-machine pool = N independent emitters.** Identity keyed on the
87
+ channel-set (user) / topic+uid (operator), NOT a per-machine id — so the SAME user/operator
88
+ across N machines is ONE record, never N duplicates.
89
+ - **The topic-operator untrusted-replicated invariant scales:** on N machines only the LOCAL
90
+ authenticated binding is authoritative for the principal; replicated records from N-1 peers
91
+ are advisory. A re-bind to a NEW operator (different uid) is a DIFFERENT record (different
92
+ key), so a replica can never overwrite the local binding.
93
+ - **No LAN/broadcast assumption.** Rides the existing per-peer replicated-store substrate.
94
+ - **Offline-peer erasure:** a removed user / unbound operator propagates an op:delete tombstone
95
+ keyed on the SAME identity surface, so an erased record stays erased on a peer that was offline
96
+ at delete time.
97
+
98
+ ## Migration parity
99
+ - ConfigDefaults: two new dark blocks (no migrateConfig needed — an absent per-store key resolves
100
+ to dark, the safe default; identical to the WS2.2–2.5 siblings).
101
+ - CLAUDE.md template (`templates.ts`) + a chained migrator else-if in `PostUpdateMigrator` splice
102
+ the two new One Memory bullets — ESPECIALLY the topic-operator UNTRUSTED-REPLICATED-OPERATOR
103
+ invariant — into already-deployed agents before any operator enables the replication. Idempotent
104
+ (guarded by the unique 'User registry is the SECOND PII store' marker), with a focused test.
105
+ - devGatedFeatures: two new DARK_GATE_EXCLUSIONS entries (optional-integration).
106
+ - Docs: two new `under-the-hood.md` class blocks (≥2 mentions each — docs-coverage passes).
107
+
108
+ ## 5-lens adversarial verdict (folded as named tests)
109
+ 1. **Untrusted-replicated-operator (THE blocker)** — `untrusted-replicated-operator-never-authoritative`:
110
+ the foreign render ALWAYS says NOT the verified operator; the module exposes NO apply/set/establish
111
+ export; the wiring test proves `getOperator()` authority is UNCHANGED by a replicated record. PASS.
112
+ 2. **recordKey identity** — `recordKey-identity-collapses-cross-machine`: same channel-set/topic+uid →
113
+ one key regardless of local id; a different uid is a different record. PASS.
114
+ 3. **disclosure-min / PII leak** — `disclosure-min-strips-local-id` (userId never on wire),
115
+ topic-operator projection exactly `{platform,uid,names,boundAt}`, `64KB-named-error`, `type-clamp`
116
+ (markup injection blocked, path-shaped slug jailed). PASS.
117
+ 4. **tombstone erasure** — `op:delete-tombstone-erasure`: tombstone keyed on the SAME identity surface;
118
+ schema op:delete branch accepts it. PASS.
119
+ 5. **dark-ship inertness** — `dark-ship-strict-noop`: no emitter ⇒ manager behaves byte-identically;
120
+ E2E DISABLED → 503. PASS.
121
+
122
+ No residual blockers. Known accepted bound: a compromised same-operator peer can inject advisory
123
+ context (cannot escalate to authority; one-operator blast radius).