@camstack/system 1.2.353 → 1.2.355

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 (82) hide show
  1. package/dist/addon-runner.js +1 -1
  2. package/dist/addon-runner.mjs +1 -1
  3. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/alerts/alerts.addon.js +1 -1
  8. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  9. package/dist/builtins/autotrack/index.js +1 -1
  10. package/dist/builtins/autotrack/index.mjs +1 -1
  11. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  12. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  13. package/dist/builtins/calendars/calendar-prefs-store.d.ts +7 -0
  14. package/dist/builtins/calendars/calendars.addon.js +3 -2
  15. package/dist/builtins/calendars/calendars.addon.mjs +3 -2
  16. package/dist/builtins/camera-grid/index.js +1 -1
  17. package/dist/builtins/camera-grid/index.mjs +1 -1
  18. package/dist/builtins/composer/composer.addon.js +56 -5
  19. package/dist/builtins/composer/composer.addon.mjs +56 -5
  20. package/dist/builtins/console-logging/index.js +1 -1
  21. package/dist/builtins/console-logging/index.mjs +1 -1
  22. package/dist/builtins/core-blocks/block-settings-store.d.ts +5 -0
  23. package/dist/builtins/core-blocks/core-blocks.addon.js +7 -2
  24. package/dist/builtins/core-blocks/core-blocks.addon.mjs +7 -2
  25. package/dist/builtins/device-manager/device-manager.addon.js +3 -3
  26. package/dist/builtins/device-manager/device-manager.addon.mjs +3 -3
  27. package/dist/builtins/hub-forwarder/index.js +1 -1
  28. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  29. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  30. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  31. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  32. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  33. package/dist/builtins/local-network/local-network.addon.d.ts +21 -6
  34. package/dist/builtins/local-network/local-network.addon.js +81 -54
  35. package/dist/builtins/local-network/local-network.addon.mjs +81 -55
  36. package/dist/builtins/loki-logging/index.js +1 -1
  37. package/dist/builtins/loki-logging/index.mjs +1 -1
  38. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  39. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  40. package/dist/builtins/platform-probe/index.js +1 -1
  41. package/dist/builtins/platform-probe/index.mjs +1 -1
  42. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  43. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/snapshot/index.js +1 -1
  45. package/dist/builtins/snapshot/index.mjs +1 -1
  46. package/dist/builtins/sqlite-storage/analyze-stats.d.ts +0 -2
  47. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  48. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  49. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +9 -11
  50. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  51. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  52. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +2 -2
  53. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +2 -2
  54. package/dist/builtins/system-config/system-config.addon.js +1 -1
  55. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  56. package/dist/builtins/winston-logging/index.js +1 -1
  57. package/dist/builtins/winston-logging/index.mjs +1 -1
  58. package/dist/{child-cap-dispatch-CvYlCq60.js → child-cap-dispatch-CqV-7-QZ.js} +27 -86
  59. package/dist/{child-cap-dispatch-C6IpRb4P.mjs → child-cap-dispatch-DMx2axev.mjs} +28 -81
  60. package/dist/{composition-sources-CAFDvTRs.js → composition-sources-Bk-MjK1D.js} +1 -1
  61. package/dist/{composition-sources-BGlDi3CT.mjs → composition-sources-Dpl1G0Gr.mjs} +1 -1
  62. package/dist/{dist-CXVXFdJX.js → dist-BWicEEVA.js} +233 -79
  63. package/dist/{dist-Cm556q2j.mjs → dist-OCi0K-iM.mjs} +216 -80
  64. package/dist/http/reverse-proxy.d.ts +11 -1
  65. package/dist/index.d.ts +1 -1
  66. package/dist/index.js +71 -56
  67. package/dist/index.mjs +72 -56
  68. package/dist/kernel/config-schema.d.ts +1 -0
  69. package/dist/kernel/event-plane-report.d.ts +7 -36
  70. package/dist/kernel/fs-utils.d.ts +1 -5
  71. package/dist/kernel/heap-spaces.d.ts +2 -23
  72. package/dist/kernel/index.d.ts +0 -2
  73. package/dist/kernel/moleculer/event-bus-core.d.ts +6 -28
  74. package/dist/kernel/moleculer/process-service.d.ts +2 -5
  75. package/dist/kernel/moleculer/runner-native-allocator.d.ts +1 -6
  76. package/dist/kernel/transport/index.d.ts +1 -1
  77. package/dist/kernel/transport/local-child-registry.d.ts +8 -41
  78. package/dist/kernel/transport/uds-event-bridge.d.ts +2 -2
  79. package/dist/{retired-settings-keys-D24IW4qo.js → retired-settings-keys-DLJ7MvIB.js} +1 -1
  80. package/dist/{retired-settings-keys-DzkSqnH0.mjs → retired-settings-keys-TDzxE6GA.mjs} +1 -1
  81. package/package.json +1 -1
  82. package/dist/kernel/heap-allocation-sample.d.ts +0 -107
@@ -22,27 +22,13 @@
22
22
  * on that runner also counts page-cache reads and it owns a vector store, so the
23
23
  * correlation is not an attribution. `fanoutTop` turns it into one.
24
24
  *
25
- * ## And the burn-in that has been running forever
26
- *
27
- * `event-bus-core.ts:310` states the procedure in its own words: *"Recommended
28
- * first fleet-wide enable: `shadow` on both, watch the suppressed counters
29
- * (`getMoleculerEventStats` / `getChildEventStats`), then flip to `filter` once
30
- * burn-in shows zero would-be-starved deliveries."*
31
- *
32
- * The hub runs with `CAMSTACK_MOLECULER_EVENT_FANOUT=shadow` — which computes
33
- * the drop decision, counts the would-suppresses and **still delivers every
34
- * event** — and **neither counter has ever had a production caller**: both
35
- * functions are reachable only from barrel re-exports and unit tests. So the
36
- * burn-in has no end condition, and the promotion to `filter` never happened
37
- * because the evidence that would authorise it was never surfaced. This module
38
- * surfaces it. It changes no default and flips no env: the promotion stays a
39
- * one-env decision for the operator, and it now has a number behind it.
40
- *
41
- * Read the modes with the counts, always. A suppressed count of 0 means
42
- * "nothing would have been dropped" under `shadow` and "nothing WAS dropped"
43
- * under `filter`, and those are different claims. A count printed without its
44
- * regime is unreadable, and the regime is read ONCE at construction — invisible
45
- * at runtime until now.
25
+ * ## Both planes always filter
26
+ *
27
+ * The cross-node plane ran a `shadow` burn-in (`CAMSTACK_MOLECULER_EVENT_FANOUT`)
28
+ * with no end condition, and the UDS plane carried the same three-mode switch
29
+ * (`CAMSTACK_UDS_EVENT_FANOUT`). Both switches were removed on 2026-10-06: a
30
+ * suppressed count now always means "this many WERE dropped", and the line no
31
+ * longer prints a regime because there is only one.
46
32
  *
47
33
  * ## The fail-open nobody can see
48
34
  *
@@ -81,16 +67,7 @@
81
67
  * `fanoutOrphans` counts what was serialised and walked across every child with
82
68
  * zero subscribers. A suppressed pair was measured at **255 ns** — 1.84 ms/s of
83
69
  * event loop at this rate — so the filter is not the cost; the emit is.
84
- *
85
- * ## What this is NOT evidence of
86
- *
87
- * `shadow` is the CROSS-NODE plane. The local UDS plane defaults to `filter` and
88
- * its env is unset, so it is filtering. hub-main's ~44 000 socket syscalls/s are
89
- * mostly to LOCAL runners, so the shadow mode is a real defect and is **not**
90
- * established as the source of that load. Do not read these two facts as one.
91
70
  */
92
- /** Fan-out regime for one plane. Same three values on both. */
93
- export type EventFanoutMode = 'filter' | 'shadow' | 'broadcast';
94
71
  /** One child's fan-out counters, as the registry keeps them (cumulative). */
95
72
  export interface ChildFanoutSample {
96
73
  readonly childId: string;
@@ -127,7 +104,6 @@ export interface ChildFanoutRegistry {
127
104
  readonly listChildren: () => readonly ChildFanoutRegistryChild[];
128
105
  readonly getChildEventStats: (childId: string) => ChildFanoutRegistryStats | null;
129
106
  readonly undeclaredChildCount: () => number;
130
- readonly eventFanoutMode: EventFanoutMode;
131
107
  readonly categoryFanout: () => readonly CategoryFanoutSample[];
132
108
  readonly categoryCensusOverflow: () => number;
133
109
  }
@@ -138,8 +114,6 @@ export interface CrossNodeEventStats {
138
114
  }
139
115
  /** One cumulative reading of both planes. */
140
116
  export interface EventPlaneCounters {
141
- readonly udsMode: EventFanoutMode;
142
- readonly crossNodeMode: EventFanoutMode;
143
117
  readonly children: readonly ChildFanoutSample[];
144
118
  readonly childrenConnected: number;
145
119
  readonly childrenUndeclared: number;
@@ -156,7 +130,6 @@ export type EventPlaneReader = () => EventPlaneCounters | undefined;
156
130
  export interface EventPlaneSources {
157
131
  readonly registry: () => ChildFanoutRegistry | null;
158
132
  readonly crossNodeStats: () => CrossNodeEventStats | null;
159
- readonly crossNodeMode: () => EventFanoutMode;
160
133
  }
161
134
  /**
162
135
  * Build a reader over the two registries.
@@ -183,8 +156,6 @@ export declare function createEventPlaneReader(sources: EventPlaneSources): Even
183
156
  export declare const EVENT_PLANE_TOP_N = 5;
184
157
  /** Both planes over one heartbeat window. */
185
158
  export interface EventPlaneWindow {
186
- readonly udsMode: EventFanoutMode;
187
- readonly crossNodeMode: EventFanoutMode;
188
159
  readonly childrenConnected: number;
189
160
  readonly childrenUndeclared: number;
190
161
  readonly fanoutSent: number;
@@ -26,8 +26,7 @@ export declare function copyDirRecursive(src: string, dest: string): Promise<voi
26
26
  * `addons/` stays node_modules-free, which is what lets the backup tar the whole
27
27
  * folder with no exclusion list (see ADR-0027). An addon that genuinely needs an
28
28
  * un-bundleable runtime dep declares it explicitly in
29
- * `camstack.runtimeDependencies`; the debug escape hatch
30
- * `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy install-everything path.
29
+ * `camstack.runtimeDependencies`.
31
30
  *
32
31
  * (Historically this mirrored the build preset's COMMON_NATIVE_DEPS and
33
32
  * per-addon-installed node-av/sharp/onnxruntime-node/ssh2/werift/systeminformation
@@ -49,9 +48,6 @@ export declare const RUNTIME_NATIVE_KEEP: readonly string[];
49
48
  * `dependencies` so `--omit=peer` installs can't drop them (pipeline's
50
49
  * patched `werift`).
51
50
  *
52
- * Escape hatch: `CAMSTACK_INSTALL_FULL_DEPS=1` restores the legacy behaviour
53
- * (strip only @camstack/*) for debugging a suspected undeclared runtime dep.
54
- *
55
51
  * Returns a new object (immutable).
56
52
  */
57
53
  export declare function stripBundledDeps(pkg: Record<string, unknown>): Record<string, unknown>;
@@ -88,22 +88,6 @@ export declare function selectReportedSpaces(spaces: readonly HeapSpaceUsage[],
88
88
  * a query someone already wrote.
89
89
  */
90
90
  export declare function formatHeapSpaces(spaces: readonly HeapSpaceUsage[], minMb?: number): string;
91
- /**
92
- * Env var that authorises a heap snapshot on SIGUSR2.
93
- *
94
- * A snapshot is an admin mutation on a production hub: `writeHeapSnapshot`
95
- * streams a file the size of the heap to `/tmp` and stops the world while it
96
- * walks it — on the recorder that is a multi-GB file and a stall measured in
97
- * seconds. The per-space breakdown is ~1.2 µs and changes nothing. Welding them
98
- * to one signal priced the free answer at the cost of the expensive one.
99
- */
100
- /**
101
- * Whether the operator has authorised the snapshot half of SIGUSR2.
102
- *
103
- * Explicit `'on'` only. Anything else — unset, empty, `'true'`, `'1'` — is NOT
104
- * authorisation: a multi-GB stop-the-world write must never be reachable by a
105
- * value someone set for a different purpose.
106
- */
107
91
  /** What a diagnostic report is ABOUT. */
108
92
  export interface HeapDiagnosticRequest {
109
93
  /** The runner's nodeId, so the line groups with its `[mem]` heartbeat. */
@@ -115,19 +99,14 @@ export interface HeapDiagnosticRequest {
115
99
  export interface HeapDiagnosticDeps {
116
100
  readonly readMemory: () => NodeJS.MemoryUsage;
117
101
  readonly readSpaces: HeapSpaceReader;
118
- readonly env: NodeJS.ProcessEnv;
119
102
  }
120
103
  /**
121
- * The SIGUSR2 report — memory + the FULL per-space breakdown, always; the
122
- * snapshot NEVER — see the note in the body.
104
+ * The SIGUSR2 report — memory + the FULL per-space breakdown; never a heap
105
+ * snapshot (D718) — see the note in the body.
123
106
  *
124
107
  * The breakdown here keeps every non-empty space at 0.1 MB, unlike the
125
108
  * heartbeat's filtered whole-MB pair: this is a hand-fired diagnostic read once
126
109
  * by a human who asked for it, so completeness costs nothing. The heartbeat runs
127
110
  * unattended on every runner forever, so it pays for every field it prints.
128
- *
129
- * A refused snapshot SAYS SO. A branch that drops work silently reads as "it was
130
- * never requested", and this one is fired by an operator who is standing there
131
- * waiting for a file.
132
111
  */
133
112
  export declare function emitHeapDiagnosticReport(request: HeapDiagnosticRequest, deps?: HeapDiagnosticDeps): void;
@@ -45,8 +45,6 @@ export { createCoreCapService, CORE_CAP_SERVICE_NAME } from './moleculer/core-ca
45
45
  export type { CoreCapAction, CoreCapCallOrigin, CoreCapServiceOptions, } from './moleculer/core-cap-service.js';
46
46
  export { createAddonContext, createUdsAddonContext, setHubConnected, adaptBrokerToCluster, registerEventBusService, setNodeEventInterest, getMoleculerEventStats, subscribePassthrough, getBrokerEventBus, clusterEventTopic, EVENT_TOPIC_PREFIX, } from './moleculer/addon-context-factory.js';
47
47
  export type { MoleculerEventStats } from './moleculer/addon-context-factory.js';
48
- export type { MoleculerEventFanoutMode } from './moleculer/event-bus-core.js';
49
- export { readMoleculerFanoutMode } from './moleculer/event-bus-core.js';
50
48
  export { HubLogForwarder } from './moleculer/hub-log-forwarder.js';
51
49
  export type { AddonContextOptions } from './moleculer/addon-context-factory.js';
52
50
  export { createHubService } from './moleculer/hub-service.js';
@@ -142,31 +142,12 @@ export declare const RING_BUFFER_DENY_PATTERNS: readonly string[];
142
142
  export declare const MAX_RECENT_EVENTS = 1000;
143
143
  export declare function isHighFrequencyCategory(category: string): boolean;
144
144
  /**
145
- * Fan-out mode for cross-node (Moleculer) event delivery, read from the
146
- * `CAMSTACK_MOLECULER_EVENT_FANOUT` env. The inter-node analogue of the
147
- * intra-host `CAMSTACK_UDS_EVENT_FANOUT` gate (`local-child-registry.ts`):
148
- * - `filter` (default) — drop an inbound cross-node event whose category
149
- * no local subscriber on THIS node wants (the union of its children's
150
- * declared patterns).
151
- * - `shadow` — compute the drop decision + count would-suppresses, but
152
- * STILL deliver every event (burn-in: prove zero would-be-starved deliveries
153
- * before flipping to `filter`).
154
- * - `broadcast` — ignore the gate entirely (pre-D2 behaviour).
155
- *
156
- * ROLLBACK CONTRACT (operators, read this): this env governs ONLY the inter-node
157
- * (Moleculer) gate. The intra-host UDS fan-out has a SEPARATE, independent
158
- * kill-switch, `CAMSTACK_UDS_EVENT_FANOUT` (see `local-child-registry.ts`). A
159
- * FULL rollback to pre-D2 / pre-#44 delivery therefore requires BOTH env vars
160
- * set to `broadcast` AND a process restart on EVERY node (hub + all agents) —
161
- * each is read ONCE at registration/construction, so a running process will not
162
- * pick up a change. Flipping only one leg leaves the other filtering and yields
163
- * inconsistent behaviour. Recommended first fleet-wide enable: `shadow` on both,
164
- * watch the suppressed counters (`getMoleculerEventStats` /
165
- * `getChildEventStats`), then flip to `filter` once burn-in shows zero
166
- * would-be-starved deliveries.
145
+ * Cross-node (Moleculer) inbound gate: an inbound cross-node event whose
146
+ * category no local subscriber on THIS node wants (the union of its children's
147
+ * declared patterns) is dropped and counted (`suppressed`). It always filters —
148
+ * the `CAMSTACK_MOLECULER_EVENT_FANOUT` shadow/broadcast modes were removed on
149
+ * 2026-10-06; the intra-host analogue is `LocalChildRegistry.childWantsEvent`.
167
150
  */
168
- export type MoleculerEventFanoutMode = 'filter' | 'shadow' | 'broadcast';
169
- export declare function readMoleculerFanoutMode(): MoleculerEventFanoutMode;
170
151
  /**
171
152
  * A node's inbound-interest snapshot used by {@link crossNodeAcceptsCategory}.
172
153
  * - `retainRecent` — the receiving bus retains events for `getRecent`/audit
@@ -185,16 +166,13 @@ export interface CrossNodeInterestSnapshot {
185
166
  /**
186
167
  * Does this node want to accept an inbound cross-node event in `category`?
187
168
  * The receiving-side mirror of `LocalChildRegistry.childWantsEvent`:
188
- * - `broadcast` mode → always (gate disabled).
189
169
  * - a retaining bus (hub main) → always (it serves `getRecent` + admin-ui;
190
170
  * its interest is genuinely everything).
191
171
  * - undeclared interest (`null`) → always (fail-open).
192
172
  * - else the declared union must match via `matchesPattern` — the SAME
193
173
  * function the local subscriber map-key gate uses, giving delivery parity.
194
- * `shadow` is handled by the caller (it counts the would-suppress but still
195
- * delivers), exactly like the UDS fan-out.
196
174
  */
197
- export declare function crossNodeAcceptsCategory(mode: MoleculerEventFanoutMode, snapshot: CrossNodeInterestSnapshot, category: string): boolean;
175
+ export declare function crossNodeAcceptsCategory(snapshot: CrossNodeInterestSnapshot, category: string): boolean;
198
176
  /**
199
177
  * Deliver `event` to all matching local subscribers and — ONLY on a bus that
200
178
  * opted into retention (`state.retainRecent`, i.e. the hub main process) and
@@ -95,9 +95,8 @@ export declare const HEAVY_MAX_OLD_MB_DEFAULT = 1024;
95
95
  * --v8-pool-size=2 9 threads
96
96
  * --v8-pool-size=0 18 threads
97
97
  *
98
- * So a value below 1 omits the flag entirely rather than being passed through —
99
- * the same trap as `MALLOC_ARENA_MAX=0` in `runner-native-allocator.ts`. To turn
100
- * the tuning off, use `CAMSTACK_RUNNER_HEAP_TUNING=off`.
98
+ * So the flag is only ever passed with a value of at least 1 — the same trap as
99
+ * `MALLOC_ARENA_MAX=0` in `runner-native-allocator.ts`.
101
100
  *
102
101
  * ## What is deliberately NOT bounded
103
102
  *
@@ -110,8 +109,6 @@ export declare const HEAVY_MAX_OLD_MB_DEFAULT = 1024;
110
109
  * ~58 more threads for serialized filesystem I/O in runners whose I/O profile
111
110
  * has not been measured, on a media system. A thread saving is not worth a
112
111
  * media gap.
113
- *
114
- * Override: `CAMSTACK_RUNNER_LIGHT_V8_POOL_SIZE`.
115
112
  */
116
113
  export declare const LIGHT_V8_POOL_SIZE_DEFAULT = 2;
117
114
  interface SpawnedProcess {
@@ -85,12 +85,7 @@ export interface RunnerNativeAllocatorEnv {
85
85
  * restores the glibc/sharp defaults. Recoverable without a rebuild.
86
86
  * 2. A value the operator already put in the environment (`MALLOC_ARENA_MAX`,
87
87
  * `VIPS_CONCURRENCY`) — inherited verbatim, never overwritten.
88
- * 3. `CAMSTACK_RUNNER_MALLOC_ARENA_MAX` — the CamStack override.
89
- * 4. The defaults above.
90
- *
91
- * A nonsense override falls back to the default rather than being passed through:
92
- * glibc reads `MALLOC_ARENA_MAX=0` as "unbounded", which is the very state this
93
- * exists to leave.
88
+ * 3. The defaults above.
94
89
  */
95
90
  export declare function runnerNativeAllocatorEnv(parentEnv: NodeJS.ProcessEnv, platform?: NodeJS.Platform): RunnerNativeAllocatorEnv;
96
91
  /**
@@ -10,7 +10,7 @@ export { PeerAnsweredError } from './peer-answered-error.js';
10
10
  export { UdsLocalTransportServer, UdsLocalTransportClient } from './uds-local-transport.js';
11
11
  export { createLocalTransport } from './create-local-transport.js';
12
12
  export type { ChildCapDescriptor, RegisterMessage, ChildLogMessage, ChildEventMessage, ChildToParentRequest, CapCallMessage, CapCallInput, CapCallOutMessage, AddonCallMessage, AddonCallInput, AddonCallTarget, AddonSettingsMethod, ParentToChildRequest, RegisteredChild, SetLogLevelMessage, } from './child-cap-protocol.js';
13
- export { LocalChildRegistry, afterWorkerOnlineAnnounce, UDS_NO_ROUTE_PREFIX } from './local-child-registry.js';
13
+ export { LocalChildRegistry, afterWorkerOnlineAnnounce, UDS_NO_ROUTE_PREFIX, } from './local-child-registry.js';
14
14
  export type { LocalChildRegistryOptions, LocalChildRegistryLogger, ChildLifecycleEvents, } from './local-child-registry.js';
15
15
  export type { LocalChildClientOptions, AddonCallHandler } from './local-child-client.js';
16
16
  export { LocalChildClient } from './local-child-client.js';
@@ -29,17 +29,6 @@ export interface ForwardCensus {
29
29
  * check.
30
30
  */
31
31
  export declare const PRE_REGISTER_PEER_ID = "(pre-register)";
32
- /**
33
- * Fan-out mode for parent→child event delivery, from the
34
- * `CAMSTACK_UDS_EVENT_FANOUT` env (read once at registry construction):
35
- * - `filter` (default) — apply the subscription gate; a child receives a
36
- * category only if one of its declared patterns matches.
37
- * - `shadow` — compute the gate decision + count would-suppresses, but
38
- * STILL send every event (burn-in: prove zero would-be-starved deliveries).
39
- * - `broadcast` — ignore the gate entirely (today's behaviour); the operator's
40
- * one-env rollback without redeploying runners.
41
- */
42
- export type UdsEventFanoutMode = 'filter' | 'shadow' | 'broadcast';
43
32
  /** Per-child event fan-out counters (sent = delivered, suppressed = gated/would-gate). */
44
33
  export interface ChildEventStats {
45
34
  sent: number;
@@ -56,8 +45,7 @@ export interface ChildEventStats {
56
45
  * sums them concludes the cluster emits an order of magnitude more than it does.
57
46
  *
58
47
  * `wanted` is the number of (event × child) pairs whose SUBSCRIPTION matched —
59
- * the gate answer, not the delivery answer, so `broadcast`/`shadow` mode (which
60
- * deliver regardless) still report the truth. `wanted === 0` over a window means
48
+ * the gate answer, which is also the delivery answer. `wanted === 0` over a window means
61
49
  * the category was serialised and walked across every child and **nobody asked
62
50
  * for it**: pure waste, and the one finding worth acting on.
63
51
  */
@@ -340,8 +328,6 @@ export declare class LocalChildRegistry {
340
328
  private readonly capUsageObserver?;
341
329
  /** Tracks capNames already logged as UDS-routed; one INFO line per capName per process. */
342
330
  private readonly egressRoutedCaps;
343
- /** Active event fan-out mode, read once from `CAMSTACK_UDS_EVENT_FANOUT`. */
344
- private readonly fanoutMode;
345
331
  /** Per-child event fan-out counters (sent / suppressed). */
346
332
  private readonly childEventStats;
347
333
  /** D467: per-category production census (cumulative). See {@link CategoryFanoutSample}. */
@@ -374,7 +360,7 @@ export declare class LocalChildRegistry {
374
360
  /**
375
361
  * Per-child event fan-out counters (`{ sent, suppressed }`) or `null` if the
376
362
  * child has no recorded events yet. Exposed for the starvation-verification
377
- * surface (shadow burn-in + operator debug).
363
+ * surface (operator debug).
378
364
  */
379
365
  getChildEventStats(childId: string): ChildEventStats | null;
380
366
  /**
@@ -420,16 +406,6 @@ export declare class LocalChildRegistry {
420
406
  * `decoded` half of an entry, next to the bytes it carried.
421
407
  */
422
408
  readActionCensus(): CapActionReading;
423
- /**
424
- * The regime the counters above were produced under, read once from
425
- * `CAMSTACK_UDS_EVENT_FANOUT` at construction.
426
- *
427
- * A suppressed count means "nothing WAS dropped" under `filter` and "nothing
428
- * WOULD have been dropped" under `shadow`. Those are different claims, and
429
- * until this getter existed the mode was invisible at runtime — the counters
430
- * were readable and the regime that produced them was not.
431
- */
432
- get eventFanoutMode(): UdsEventFanoutMode;
433
409
  /**
434
410
  * Connected children that never declared a subscription pattern set.
435
411
  *
@@ -443,27 +419,18 @@ export declare class LocalChildRegistry {
443
419
  */
444
420
  undeclaredChildCount(): number;
445
421
  /**
446
- * Does `entry` want to receive an event in `category`? Honours the fan-out
447
- * mode: `broadcast` → always; undeclared patterns (`null`) → always
448
- * (fail-open); else the child's declared set must match via `matchesPattern`
449
- * — the SAME function the child's own `deliverShared` map-key gate uses,
450
- * giving provable delivery parity. `shadow` is handled by the caller (it
451
- * counts the would-suppress but still sends).
422
+ * Does `entry` want to receive an event in `category`? Undeclared patterns
423
+ * (`null`) → always (fail-open, counted by {@link undeclaredChildCount});
424
+ * else the child's declared set must match via `matchesPattern` — the SAME
425
+ * function the child's own `deliverShared` map-key gate uses, giving provable
426
+ * delivery parity. The parent always filters: the `CAMSTACK_UDS_EVENT_FANOUT`
427
+ * shadow/broadcast modes were removed on 2026-10-06.
452
428
  *
453
429
  * NOTE: this gate must NOT consult `RING_BUFFER_DENY_PATTERNS` /
454
430
  * `isHighFrequencyCategory` — those are ring-buffer STORAGE policy; a child
455
431
  * that explicitly subscribes to a ring-denied category must still RECEIVE it.
456
432
  */
457
433
  private childWantsEvent;
458
- /**
459
- * The SUBSCRIPTION answer alone, with no fan-out-mode override.
460
- *
461
- * {@link childWantsEvent} answers "will this child be sent the event", which
462
- * under `broadcast` is `true` for everything and therefore cannot say whether
463
- * anyone actually asked. The D467 census needs the second question, so the
464
- * two are separate functions and `broadcast` mode overrides only the first.
465
- */
466
- private childSubscribesTo;
467
434
  /**
468
435
  * D2: this node's aggregate cross-node event interest — the UNION of every
469
436
  * connected child's declared category patterns. Consumed by the parent's
@@ -7,8 +7,8 @@ import { IEventBus, SystemEvent } from '@camstack/types';
7
7
  * fans an event only to children whose declared category-pattern set matches
8
8
  * `event.category` (mirror of each child's local `SharedBusState.handlers`
9
9
  * keys). A child that never declared a set (legacy/undeclared) fails OPEN and
10
- * receives everything. The `CAMSTACK_UDS_EVENT_FANOUT` env (`filter` default /
11
- * `shadow` / `broadcast`) is the registry-side kill-switch. The bridge itself
10
+ * receives everything. There is no kill-switch any more (the
11
+ * `CAMSTACK_UDS_EVENT_FANOUT` modes were removed on 2026-10-06). The bridge itself
12
12
  * needs no per-event logic change — both fan-out call sites here go through the
13
13
  * filtered `broadcastEventToChildren`. `sendEventToChild` (targeted push) is
14
14
  * NOT filtered — an explicit single-child send expresses intent.
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-CXVXFdJX.js");
1
+ const require_dist = require("./dist-BWicEEVA.js");
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
@@ -1,4 +1,4 @@
1
- import { nr as asJsonObject } from "./dist-Cm556q2j.mjs";
1
+ import { ar as asJsonObject } from "./dist-OCi0K-iM.mjs";
2
2
  //#region src/builtins/sqlite-storage/retired-settings-keys.ts
3
3
  /**
4
4
  * Is THIS node the one whose settings store is the cluster's authority?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/system",
3
- "version": "1.2.353",
3
+ "version": "1.2.355",
4
4
  "description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
5
5
  "keywords": [
6
6
  "camstack",
@@ -1,107 +0,0 @@
1
- /**
2
- * WHERE the bytes come from, without stopping the process.
3
- *
4
- * A heap SNAPSHOT answers "what is retained" and costs a stop-the-world walk
5
- * plus a multi-gigabyte write. On this hub that took the machine down twice;
6
- * the second attempt did not even finish — it left a 0-byte file and an
7
- * unresponsive host that had to be rebooted. The remotely-triggerable command
8
- * is gone (`scripts/check-no-heap-dump-command.ts`).
9
- *
10
- * V8's SAMPLING heap profiler answers a cheaper, different question: which
11
- * allocation SITES the bytes came from, statistically, with no pause and
12
- * nothing written. Measured locally: 51 ms for a window that allocated 200 000
13
- * objects.
14
- *
15
- * ## What this is NOT
16
- *
17
- * It is not retention analysis. It says where bytes were BORN, not what is
18
- * holding them alive, and a leak is about the second. It is still the right
19
- * first instrument for the recorder's ~900 MB of large objects that "no
20
- * allocation site in its tree can produce" — because naming the sites is
21
- * exactly the claim under test, and if the sites turn out to be ordinary, the
22
- * retention question is the one that survives.
23
- *
24
- * This module is the PURE half: it folds the profile V8 hands back. The
25
- * sampling belongs to the caller, so the fold is testable without a profiler.
26
- */
27
- /** One frame as the inspector protocol reports it. */
28
- export interface AllocationCallFrame {
29
- readonly functionName: string;
30
- readonly url: string;
31
- readonly lineNumber: number;
32
- }
33
- /** One node of `HeapProfiler.stopSampling`'s profile tree. */
34
- export interface AllocationProfileNode {
35
- readonly selfSize: number;
36
- readonly callFrame: AllocationCallFrame;
37
- readonly children?: readonly AllocationProfileNode[];
38
- }
39
- export interface AllocationSite {
40
- readonly functionName: string;
41
- /** `file.js:line` — what a human reads in a log line. */
42
- readonly site: string;
43
- readonly bytes: number;
44
- }
45
- /**
46
- * Fold the tree into the biggest allocation sites.
47
- *
48
- * Sites are SUMMED across call paths: one site reached from two callers is one
49
- * site, and reporting it twice at half the size is how a dominant allocator
50
- * hides in a long tail. Identity is (function, url, line) — the same line of
51
- * two files is two sites.
52
- */
53
- export declare function summariseAllocationProfile(head: AllocationProfileNode, limit: number): readonly AllocationSite[];
54
- /**
55
- * The inspector session slice this needs. Injected so the sampler is testable
56
- * without an inspector, and so nothing here reaches for a global.
57
- */
58
- export interface HeapProfilerSession {
59
- connect: () => void;
60
- disconnect: () => void;
61
- post: (method: string, paramsOrCb: unknown, maybeCb?: unknown) => void;
62
- }
63
- export interface SampleHeapAllocationsInput {
64
- readonly session: HeapProfilerSession;
65
- /** How long to sample. Bounded by the caller; this module never loops. */
66
- readonly durationMs: number;
67
- readonly limit: number;
68
- readonly wait: (ms: number) => Promise<void>;
69
- /** Bytes between samples. Larger = cheaper and coarser. */
70
- readonly samplingInterval?: number;
71
- }
72
- /**
73
- * Sample allocations for a bounded window and answer with the top sites.
74
- *
75
- * Writes NOTHING and pauses nothing. The profiler is stopped and the session
76
- * disconnected in a `finally`, because a sampler left running is a tax on the
77
- * process that outlives whoever enabled it — and the failure that made this
78
- * module necessary was a diagnostic nobody could turn off from outside.
79
- */
80
- export declare function sampleHeapAllocations(input: SampleHeapAllocationsInput): Promise<readonly AllocationSite[]>;
81
- /**
82
- * Per-runner opt-in for allocation sampling.
83
- *
84
- * Explicit `'on'` only — the same discipline the snapshot flag had. The
85
- * DIFFERENCE is what it authorises: that flag allowed a stop-the-world walk and
86
- * a multi-gigabyte write, so leaving it on in production (which is exactly what
87
- * happened) was an outage waiting for a signal. This one allows ~50 ms of
88
- * statistical sampling and one log line, so a runner left with it on is simply
89
- * a runner that reports where its bytes come from.
90
- */
91
- export declare const RUNNER_ALLOC_SAMPLE_ENV = "CAMSTACK_RUNNER_ALLOC_SAMPLE";
92
- export declare function allocationSamplingEnabled(env?: NodeJS.ProcessEnv): boolean;
93
- /** Sample on every Nth heartbeat — one sample per ~10 minutes at a 60 s beat. */
94
- export declare const ALLOCATION_SAMPLE_EVERY_N_BEATS = 10;
95
- /** How long one sample runs. Short enough that two can never overlap. */
96
- export declare const ALLOCATION_SAMPLE_WINDOW_MS = 5000;
97
- /** How many sites one log line carries. */
98
- export declare const ALLOCATION_SAMPLE_TOP_N = 8;
99
- /**
100
- * Is this the beat that samples?
101
- *
102
- * Beat 0 never samples: a runner that has just booted has allocated nothing
103
- * worth ranking. A non-positive cadence samples NEVER rather than always — a
104
- * misconfigured `0` must not turn a diagnostic into a permanent load, which is
105
- * the failure mode this whole module exists because of.
106
- */
107
- export declare function shouldSampleAllocations(beat: number, everyN: number): boolean;