@camstack/system 1.2.201 → 1.2.203

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 (62) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +12 -0
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +37 -3
  9. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +37 -3
  10. package/dist/builtins/console-logging/index.js +1 -1
  11. package/dist/builtins/console-logging/index.mjs +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  13. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  14. package/dist/builtins/device-manager/device-manager.addon.js +2 -2
  15. package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
  16. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  18. package/dist/builtins/hub-forwarder/index.js +1 -1
  19. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  20. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  21. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  22. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  24. package/dist/builtins/local-network/local-network.addon.js +1 -1
  25. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  26. package/dist/builtins/loki-logging/index.js +1 -1
  27. package/dist/builtins/loki-logging/index.mjs +1 -1
  28. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  30. package/dist/builtins/platform-probe/index.js +1 -1
  31. package/dist/builtins/platform-probe/index.mjs +1 -1
  32. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  34. package/dist/builtins/snapshot/index.js +1 -1
  35. package/dist/builtins/snapshot/index.mjs +1 -1
  36. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  38. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
  39. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
  40. package/dist/builtins/storage-orchestrator/drain-ratchet.d.ts +104 -0
  41. package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +13 -0
  42. package/dist/builtins/storage-orchestrator/location-occupancy-slice.d.ts +47 -0
  43. package/dist/builtins/storage-orchestrator/location-protection.d.ts +20 -0
  44. package/dist/builtins/storage-orchestrator/location-root-collision.d.ts +44 -0
  45. package/dist/builtins/storage-orchestrator/location-store.d.ts +12 -3
  46. package/dist/builtins/storage-orchestrator/storage-migration-coordinator.d.ts +9 -9
  47. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +47 -0
  48. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +865 -157
  49. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +865 -157
  50. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +75 -31
  51. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +45 -0
  52. package/dist/builtins/system-config/system-config.addon.js +1 -1
  53. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  54. package/dist/builtins/winston-logging/index.js +1 -1
  55. package/dist/builtins/winston-logging/index.mjs +1 -1
  56. package/dist/{dist-CcV3k-hD.js → dist-BFvWv_bz.js} +933 -546
  57. package/dist/{dist-BmJNnb_s.mjs → dist-DcMUcdeq.mjs} +862 -547
  58. package/dist/index.js +1 -1
  59. package/dist/index.mjs +1 -1
  60. package/dist/{retired-settings-keys-nLVKlhe-.mjs → retired-settings-keys-CJfgnUSb.mjs} +1 -1
  61. package/dist/{retired-settings-keys-Bd8fuwO1.js → retired-settings-keys-Dd7K3K3r.js} +1 -1
  62. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { IScopedLogger, IStorageProviderImpl, StorageAccess, StorageLocation, StorageLocationDeclaration, StorageLocationRef } from '@camstack/types';
2
+ import { ResolveRoot } from './location-root-collision.js';
2
3
  import { ILocationStore } from './location-store.js';
3
4
  export interface ListLocationsFilter {
4
5
  readonly type?: string;
@@ -184,23 +185,37 @@ export declare class StorageOrchestratorService {
184
185
  */
185
186
  attachStore(store: ILocationStore): Promise<void>;
186
187
  /**
187
- * Shout about a persisted row that is BOTH the type default and disabled.
188
+ * ONE explicit migration onto the four-state model (D385), run once per boot
189
+ * against the rows that came off disk. Idempotent: the second boot finds
190
+ * nothing to do.
188
191
  *
189
- * `upsertLocation` can now produce this (enabled is the write set; `isDefault`
190
- * is store residue). Hydrate also writes rows straight into the map, so a
191
- * hand-edited store or a row written by another build can too. It matters
192
- * because every bare-type ref still resolves through {@link getDefaultLocation}
193
- * until Stage 5 of the enabled-write-set design: on such a row
194
- * `storage.write({ location: 'eventMedia' })` and the migration coordinator's
195
- * drain destination both point at a disk the operator turned off.
192
+ * Two steps, in order, and each one is a WRITE — the point is that "absent"
193
+ * stops existing rather than being re-interpreted on every read forever:
196
194
  *
197
- * Reported, never repaired: flipping an operator's flag back on at boot would
198
- * be the system overruling the switch instead of obeying it. The coordinator
199
- * refuses the drain (`storage-migration-coordinator.drain`); the bare-ref read
200
- * path is deliberately left working, because narrowing a READ is a worse bug
201
- * than the one this line reports.
195
+ * 1. A row with no `mode` is stamped with the mode its legacy flags imply
196
+ * (`legacyModeOf`): `config.readOnly === true` → `readonly` and the
197
+ * config key is DELETED; `enabled === false` → `readonly` (the
198
+ * CONSERVATIVE direction — a state change must never start deleting
199
+ * footage on its own); everything else → `active`. `withLocationMode`
200
+ * derives `enabled` from the mode, so the two can never disagree, and
201
+ * this subsumes the D383 pass that stamped flagless rows `enabled: true`.
202
+ * 2. A type left with NO write target — only reachable from a hand-edited
203
+ * store or a row an older build wrote — gets one made `active`, chosen as
204
+ * the row the RETIRED default flag named, else the `:default`-slugged
205
+ * row, else the lexicographically first. Loudly: a class with no write
206
+ * target records nowhere, and refusing to repair it here would leave the
207
+ * hub silently unable to write with no operator action pending.
208
+ *
209
+ * An operator's explicit `readonly`/`drain`/`disabled` is never reversed by
210
+ * step 1 — only step 2 touches it, and only when the alternative is a class
211
+ * that cannot write at all.
212
+ *
213
+ * On the live hub every location is enabled with no `readOnly`, so step 1 is
214
+ * a no-op that stamps `active` and nothing else changes.
202
215
  */
203
- private reportDisabledDefaults;
216
+ private migrateOntoTheWriteSet;
217
+ /** Apply one migrated row in memory and mirror it to the store. */
218
+ private persistMigrated;
204
219
  /**
205
220
  * Inject the declaration-driven cardinality source. Called once by the
206
221
  * addon after the kernel aggregates every addon's `storageLocations`
@@ -259,22 +274,36 @@ export declare class StorageOrchestratorService {
259
274
  */
260
275
  backfillNodeIds(hubNodeId: string): Promise<void>;
261
276
  listLocations(filter?: ListLocationsFilter): readonly StorageLocation[];
262
- getDefaultLocation(type: string): StorageLocation | null;
263
277
  /**
264
- * Repoint several logical defaults as one in-memory commit. The migration
265
- * coordinator persists its `repointing` phase before calling this method, so
266
- * a process crash during the backing-store writes is recovered by replaying
267
- * the same idempotent target set before anyone resumes writers.
278
+ * The WRITE SET of a type: every enabled location of it, in stable id order.
279
+ * This replaced `getDefaultLocation` (D383) — a type does not have one write
280
+ * target any more, it has a pool, and every consumer that must pick one picks
281
+ * from here by its own rule (the recorder by headroom, a drain by an operator
282
+ * -named destination).
268
283
  */
269
- setDefaultLocations(targetByType: ReadonlyMap<string, string>): Promise<void>;
284
+ writeTargets(type: string): readonly StorageLocation[];
270
285
  /**
271
- * Insert or update a location. If `isDefault: true`, atomically
272
- * demotes any other default for the same type — operators always see
273
- * exactly one default per type.
286
+ * Change the WRITE SET as one compensated commit: each named location is
287
+ * enabled (it joins the pool) or disabled (it becomes read-only — still read,
288
+ * still played back, still age-swept, still drained).
289
+ *
290
+ * This is the cutover verb, and its only caller is the migration coordinator,
291
+ * which persists its `repointing` phase BEFORE calling so a crash mid-write
292
+ * is recovered by replaying the same idempotent set before writers resume.
274
293
  *
275
- * When a persistence store is wired (Task 6), the new record AND any
276
- * implicitly-demoted siblings are persisted before the in-memory map
277
- * mutation returns. Persistence errors propagate to the caller.
294
+ * It moves ONLY the locations it is given: a cutover from A to C on a class
295
+ * that also writes to B leaves B in the pool, because the operator's pool is
296
+ * the authority and a migration is not a licence to shrink it. The commit is
297
+ * refused when it would leave a write-serving type with nothing enabled —
298
+ * the same refusal `upsertLocation` applies, judged on the RESULT so an
299
+ * enable and a disable in one commit are weighed together.
300
+ */
301
+ setWriteTargets(enabledByLocationId: ReadonlyMap<string, boolean>): Promise<void>;
302
+ /**
303
+ * Insert or update a location.
304
+ *
305
+ * When a persistence store is wired (Task 6), the record is mirrored to it;
306
+ * the mirror is fire-and-forget and its errors reach the logger.
278
307
  */
279
308
  /**
280
309
  * Refuse a `(location kind, provider)` pair the kind cannot use.
@@ -310,8 +339,7 @@ export declare class StorageOrchestratorService {
310
339
  /**
311
340
  * Remove a location. Refuses the last location of a type and the last
312
341
  * enabled location of a type. `isSystem` is informational — a frozen
313
- * recordings `:default` is deletable once a sibling is live. Deleting
314
- * the flagged default promotes an enabled sibling. Occupancy still
342
+ * recordings `:default` is deletable once a sibling is live. Occupancy still
315
343
  * refuses unless `force` is set; force never overrides uniqueness /
316
344
  * last-enabled.
317
345
  */
@@ -392,9 +420,11 @@ export declare class StorageOrchestratorService {
392
420
  * declarations on a populated map is a no-op (each declared `id`
393
421
  * already resolves to an existing `<id>:default`).
394
422
  *
395
- * Convention: the bare-type ref `'recordings'` resolves via
396
- * `getDefaultLocation('recordings')` (walks `isDefault === true`); the
397
- * actual stored `id` is `'recordings:default'` so it satisfies the
423
+ * The seeded row is born ENABLED — a fresh install must be able to write the
424
+ * moment it boots, and `enabled` is the only write switch there is (D383).
425
+ * The `:default` suffix is a NAME kept for idempotency across existing
426
+ * installs, not a flag: the stored `id` is `'recordings:default'` so it
427
+ * satisfies the
398
428
  * `^[a-z][a-z0-9-]*:[a-z0-9-]+$` regex on `StorageLocationSchema.id`.
399
429
  *
400
430
  * `basePath` is the storage root (e.g. `<CAMSTACK_DATA>`). Each
@@ -420,6 +450,20 @@ export declare class StorageOrchestratorService {
420
450
  readonly backupBasePath?: string;
421
451
  readonly declarations: readonly StorageLocationDeclaration[];
422
452
  }): void;
453
+ /**
454
+ * The same-type physical-root refusal (D389).
455
+ *
456
+ * An unresolvable root — another node's disk, a remote provider, a path that
457
+ * does not exist yet — WARNS and lets the write through. Refusing on a read
458
+ * that could not be taken blocks the operator on a doubt, and the recorder's
459
+ * demotion still catches what slips past (D49's spirit).
460
+ */
461
+ private refuseSameTypeRootCollision;
462
+ /** Injectable so a test can drive symlinks and unresolvable paths without
463
+ * touching a real filesystem. Production takes the shared derivation. */
464
+ private resolveRoot;
465
+ /** Test seam for {@link refuseSameTypeRootCollision}. */
466
+ setRootResolver(resolveRoot: ResolveRoot): void;
423
467
  /** Internal: check whether any location of the given type exists. */
424
468
  private hasAnyLocationOfType;
425
469
  }
@@ -1,4 +1,26 @@
1
1
  import { IScopedLogger, IStorageEvictableProvider } from '@camstack/types';
2
+ import { DrainProgress, DrainState } from './drain-ratchet.js';
3
+ /**
4
+ * One draining location and the ACTIVE locations of its class the drain is
5
+ * paced against (D386). Supplied by the orchestrator, which is the only thing
6
+ * that knows a location's mode.
7
+ */
8
+ export interface DrainPlanEntry {
9
+ readonly locationId: string;
10
+ /** Locations of the SAME class whose growth the drain is matched to. Empty
11
+ * means the pace is unmeasurable and the cap stands still. */
12
+ readonly activePeerLocationIds: readonly string[];
13
+ }
14
+ /**
15
+ * Durable home for the ratchet state. It MUST survive a process restart: a cap
16
+ * recomputed from today's usage starts again at the top and silently undoes
17
+ * every byte of progress.
18
+ */
19
+ export interface DrainStateStore {
20
+ load(): Promise<readonly DrainState[]>;
21
+ save(state: DrainState): Promise<void>;
22
+ clear(locationId: string): Promise<void>;
23
+ }
2
24
  /**
3
25
  * StoragePressureManager — core-owned TRIGGER for disk-space relief.
4
26
  *
@@ -50,12 +72,35 @@ export interface PressureManagerDeps {
50
72
  * independently), preserving prior single-disk behaviour.
51
73
  */
52
74
  readonly getLocationDeviceKey?: (locationId: string) => Promise<string | null>;
75
+ /** Locations in `drain` mode, each with the active peers of its class.
76
+ * Absent → no drain (the behaviour before D386). */
77
+ readonly getDrainPlan?: () => Promise<readonly DrainPlanEntry[]>;
78
+ /** Where the ratchet state lives across restarts. Absent → drain is inert:
79
+ * without persistence the cap would reset on every boot, which is worse
80
+ * than not draining. */
81
+ readonly drainState?: DrainStateStore;
53
82
  }
54
83
  export declare class StoragePressureManager {
55
84
  private readonly deps;
85
+ /** Last sweep's drain progress, by location. Read-only surface for the UI. */
86
+ private drainProgress;
56
87
  constructor(deps: PressureManagerDeps);
57
88
  /** Relieve every managed location currently under its threshold. */
58
89
  sweep(): Promise<void>;
90
+ /**
91
+ * The drain pass (D386). A `drain` location is excluded from nothing — it is
92
+ * given a monotonically descending effective usage cap and handed to the SAME
93
+ * `relieveToUsageCap` machinery every other cap uses. There is no second
94
+ * eviction path, and no operator-facing rate.
95
+ */
96
+ private sweepDrains;
97
+ /** Progress for every draining location, as of the last sweep. The read a UI
98
+ * asks for — it never triggers work of its own. */
99
+ drainProgressSnapshot(): readonly DrainProgress[];
100
+ /** Evictable bytes on one location, summed across every provider. */
101
+ private evictableUsageOf;
102
+ /** Evictable bytes across a set of locations. */
103
+ private evictableUsageOfAll;
59
104
  /** Evict oldest-first until the location's evictable usage fits `maxBytes`. */
60
105
  private relieveToUsageCap;
61
106
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-CcV3k-hD.js");
6
+ const require_dist = require("../../dist-BFvWv_bz.js");
7
7
  //#region src/builtins/system-config/system-config.addon.ts
8
8
  /**
9
9
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -1,4 +1,4 @@
1
- import { $t as hydrateSchema, Ft as errMsg, It as BaseAddon } from "../../dist-BmJNnb_s.mjs";
1
+ import { Jt as BaseAddon, dn as hydrateSchema, qt as errMsg } from "../../dist-DcMUcdeq.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-CcV3k-hD.js");
6
+ const require_dist = require("../../dist-BFvWv_bz.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { It as BaseAddon, lt as logDestinationCapability } from "../../dist-BmJNnb_s.mjs";
1
+ import { Jt as BaseAddon, ht as logDestinationCapability } from "../../dist-DcMUcdeq.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";