@camstack/system 1.2.202 → 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 (60) 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/storage-orchestrator.addon.d.ts +47 -0
  46. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +714 -58
  47. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +714 -58
  48. package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +32 -11
  49. package/dist/builtins/storage-orchestrator/storage-pressure-manager.d.ts +45 -0
  50. package/dist/builtins/system-config/system-config.addon.js +1 -1
  51. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  52. package/dist/builtins/winston-logging/index.js +1 -1
  53. package/dist/builtins/winston-logging/index.mjs +1 -1
  54. package/dist/{dist-jZb-HKI5.js → dist-BFvWv_bz.js} +730 -372
  55. package/dist/{dist-CiHYspij.mjs → dist-DcMUcdeq.mjs} +671 -373
  56. package/dist/index.js +1 -1
  57. package/dist/index.mjs +1 -1
  58. package/dist/{retired-settings-keys-DeRxo3vg.mjs → retired-settings-keys-CJfgnUSb.mjs} +1 -1
  59. package/dist/{retired-settings-keys-Dxv9S_lO.js → retired-settings-keys-Dd7K3K3r.js} +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,47 @@
1
+ import { IScopedLogger, IStorageOccupancyProvider } from '@camstack/types';
2
+ /** What one location's owners hold there, merged. */
3
+ export interface LocationOwnedBytes {
4
+ readonly bytes: number;
5
+ /** The OLDEST contributing measurement — honest about the whole figure
6
+ * rather than about its freshest part. */
7
+ readonly measuredAtMs: number;
8
+ }
9
+ export interface OccupancySliceDeps {
10
+ readonly logger: IScopedLogger;
11
+ /** Registered `storage-occupancy` providers (cross-process proxies). */
12
+ readonly getProviders: () => readonly IStorageOccupancyProvider[];
13
+ /** Every location worth asking about, at refresh time. */
14
+ readonly locationIds: () => readonly string[];
15
+ readonly now: () => number;
16
+ /** How long a figure stays servable before a refresh is kicked. */
17
+ readonly staleAfterMs?: number;
18
+ }
19
+ export declare class LocationOccupancySlice {
20
+ private readonly deps;
21
+ private slice;
22
+ private refreshing;
23
+ private lastRefreshMs;
24
+ constructor(deps: OccupancySliceDeps);
25
+ /**
26
+ * What the last completed refresh saw for this location, or `undefined` when
27
+ * nothing has reported for it. There is deliberately no fallback: unknown is
28
+ * the truth about a location nobody owns bytes on.
29
+ */
30
+ ownedFor(locationId: string): LocationOwnedBytes | undefined;
31
+ /**
32
+ * Serve-and-revalidate. Called by every read: it returns immediately, and
33
+ * kicks a background refresh when the slice is older than the window. A read
34
+ * never awaits, and never joins a refresh already in flight (D224).
35
+ */
36
+ serveAndRevalidate(): void;
37
+ /**
38
+ * Ask every provider once and replace the slice.
39
+ *
40
+ * A provider that throws contributes NOTHING and is logged — it does not
41
+ * contribute a zero, and it does not take the other providers' answers down
42
+ * with it. A location that ends up with no contribution at all simply stays
43
+ * out of the slice, which is what makes it read back as unknown.
44
+ */
45
+ refresh(): Promise<void>;
46
+ private runRefresh;
47
+ }
@@ -0,0 +1,20 @@
1
+ /** statfs of the location's volume, when this node could take it. */
2
+ export interface LocationVolumeCapacity {
3
+ readonly totalBytes: number;
4
+ readonly availableBytes: number;
5
+ }
6
+ /** One line, at most once per location per process. */
7
+ export type ProtectionNotice = (message: string, meta: Record<string, unknown>) => void;
8
+ /**
9
+ * The free-space percentage the guard enforces for one location.
10
+ *
11
+ * Order:
12
+ * 1. `config.minFreeGb`, converted against the volume total — the operator's
13
+ * criterion in the unit they set it in.
14
+ * 2. `config.minFreePercent` — the legacy per-location override, and the
15
+ * fallback when `minFreeGb` cannot be converted (no volume total: a
16
+ * remote-node or unstattable location). Falling back is the right
17
+ * direction — the alternative is a location with no guard at all.
18
+ * 3. the provider's declared default.
19
+ */
20
+ export declare function resolveMinFreePercent(config: Readonly<Record<string, unknown>>, providerDefaultPercent: number, capacity: LocationVolumeCapacity | null, notice: ProtectionNotice): number;
@@ -0,0 +1,44 @@
1
+ import { PhysicalRoot } from '@camstack/types/node';
2
+ /** The minimum a row must expose for this check. */
3
+ export interface RootCollisionCandidate {
4
+ readonly id: string;
5
+ readonly type: string;
6
+ /** Which node the path lives on. Two locations on DIFFERENT nodes can never
7
+ * collide, however identical their paths look. */
8
+ readonly nodeId?: string;
9
+ readonly config: Readonly<Record<string, unknown>>;
10
+ }
11
+ /** How this location's physical root was derived, or that it could not be. */
12
+ export type ResolveRoot = (basePath: string) => PhysicalRoot;
13
+ /** A same-type root collision, with everything the message needs to name it. */
14
+ export interface RootCollision {
15
+ readonly otherId: string;
16
+ readonly type: string;
17
+ readonly sharedRoot: string;
18
+ /** `equal` — the same directory. `nested` — one inside the other's tree. */
19
+ readonly kind: 'equal' | 'nested';
20
+ }
21
+ /** Why the check could not be made. Never a refusal — the caller warns. */
22
+ export interface RootCollisionUnknown {
23
+ readonly reason: 'no-base-path' | 'unresolvable';
24
+ readonly detail: string;
25
+ }
26
+ export type RootCollisionVerdict = {
27
+ readonly outcome: 'clear';
28
+ } | {
29
+ readonly outcome: 'collides';
30
+ readonly collision: RootCollision;
31
+ } | {
32
+ readonly outcome: 'unknown';
33
+ readonly unknown: RootCollisionUnknown;
34
+ };
35
+ /**
36
+ * Does `next` collide with anything already stored?
37
+ *
38
+ * `existing` is every other location; the row being EDITED is excluded by id,
39
+ * so re-saving a location without moving its root never refuses itself.
40
+ */
41
+ export declare function findRootCollision(next: RootCollisionCandidate, existing: Iterable<RootCollisionCandidate>, resolveRoot: ResolveRoot, storedSelf?: RootCollisionCandidate): RootCollisionVerdict;
42
+ /** The operator-facing refusal. Names the location it collides with and the
43
+ * shared root — a refusal that says only "conflict" makes the operator hunt. */
44
+ export declare function rootCollisionMessage(id: string, collision: RootCollision): string;
@@ -4,6 +4,15 @@ interface StorageOrchestratorConfig extends Record<string, unknown> {
4
4
  export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestratorConfig> {
5
5
  private service;
6
6
  private pressureManager;
7
+ /**
8
+ * How much of each location CamStack itself holds (D388).
9
+ *
10
+ * Built on first use rather than in a field initializer: `this.ctx` does not
11
+ * exist until `initialize()` runs, and a field initializer touching it throws
12
+ * in the constructor.
13
+ */
14
+ private occupancySlice;
15
+ private get occupancy();
7
16
  private pressureTimer;
8
17
  private pressureSweepInFlight;
9
18
  private migration;
@@ -98,6 +107,25 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
98
107
  * the recorder so disk-pressure is a single core concern.
99
108
  */
100
109
  private resolveLocationThresholds;
110
+ /** Location ids that have already logged the `minFreeGb` / `minFreePercent`
111
+ * redundancy. The pressure sweep runs on a timer; the notice is worth
112
+ * exactly one line per location per process, not one per minute. */
113
+ private readonly minFreeRedundancyLogged;
114
+ private logMinFreeRedundancyOnce;
115
+ /**
116
+ * The draining locations and the ACTIVE peers of their class whose growth
117
+ * paces them (D386). Rebuilt every sweep from the live mode of every
118
+ * location, so this is also what STOPS a drain: a location the operator
119
+ * switched back simply stops appearing.
120
+ */
121
+ private drainStore;
122
+ /** The drain ratchet's durable home, once a data-store engine exists. Same
123
+ * late-wiring window as the location table — on an agent it is never. */
124
+ private resolveDrainStore;
125
+ private drainPlanRefusalLogged;
126
+ private resolveDrainPlan;
127
+ /** Drain progress for every draining location, as of the last sweep. */
128
+ private drainProgress;
101
129
  /**
102
130
  * What the provider's own schema declared secret, or `undefined` when this
103
131
  * node has never heard from that provider. The distinction is the whole
@@ -106,6 +134,25 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
106
134
  private declaredSecretKeys;
107
135
  /** Which keys of a given stored config must never leave this process. */
108
136
  private secretKeysFor;
137
+ /**
138
+ * Ring the doorbell: the SET of storage locations changed (D387).
139
+ *
140
+ * A consumer that resolves locations at boot had no way to learn that the
141
+ * operator added, edited or removed one — the recorder kept writing to the
142
+ * disk set it resolved hours ago, and an operator who added a second
143
+ * recordings disk in the admin UI got nothing until something unrelated
144
+ * happened to re-resolve.
145
+ *
146
+ * Telemetry, and deliberately so (D8/D11): it carries no row, it is allowed
147
+ * to be dropped, and every consumer re-reads `listLocations` for itself and
148
+ * converges on its own periodic path anyway. A bulk edit rings it once per
149
+ * row — coalescing is the consumer's job, not this one's.
150
+ *
151
+ * Never throws into the mutation that produced it: the location IS saved,
152
+ * and a bus that will not take a telemetry event must not turn that into a
153
+ * failed upsert.
154
+ */
155
+ private announceLocationsChanged;
109
156
  /** A location with its provider's declared secrets replaced by the sentinel. */
110
157
  private redacted;
111
158
  /**