@camstack/system 1.2.157 → 1.2.159
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.
- package/dist/addon-runner.js +17 -16
- package/dist/addon-runner.mjs +2 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/sqlite-storage/vector-index-shared.d.ts +30 -5
- package/dist/builtins/sqlite-storage/vector-index-vec.d.ts +28 -6
- package/dist/builtins/storage-orchestrator/access-guards.d.ts +32 -0
- package/dist/builtins/storage-orchestrator/location-secrets.d.ts +33 -0
- package/dist/builtins/storage-orchestrator/storage-migration-coordinator.d.ts +71 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +26 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +490 -8
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +490 -8
- package/dist/builtins/storage-orchestrator/storage-orchestrator.service.d.ts +37 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-CDgIzo82.js → dist-Ck2jkBZk.js} +463 -10
- package/dist/{dist-LvKus-mT.mjs → dist-DLh4_rn3.mjs} +446 -11
- package/dist/index.js +140 -139
- package/dist/index.mjs +3 -3
- package/dist/kernel/deps/manifest-system-deps.d.ts +15 -0
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/storage-location-registry.d.ts +16 -1
- package/dist/{manifest-python-deps-DVODn-qc.js → manifest-system-deps-8boi90D9.js} +202 -7
- package/dist/{manifest-python-deps-CD14Pv0-.mjs → manifest-system-deps-tZZYG3RR.mjs} +197 -8
- package/dist/{retired-settings-keys-CV4QVdXj.mjs → retired-settings-keys-Bi0ZKBjb.mjs} +1 -1
- package/dist/{retired-settings-keys-BfAzWvPC.js → retired-settings-keys-Dp_CyuCW.js} +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { StorageLocation } from '@camstack/types';
|
|
2
|
+
/** Shared empty set for providers that declare no secrets (or are unknown). */
|
|
3
|
+
export declare const EMPTY_SECRET_KEYS: ReadonlySet<string>;
|
|
4
|
+
/** Minimal shape needed off a provider's `getProviderInfo()` result. */
|
|
5
|
+
export interface ProviderInfoLike {
|
|
6
|
+
readonly providerId: string;
|
|
7
|
+
readonly configSchema: unknown;
|
|
8
|
+
}
|
|
9
|
+
/** Secret config keys a provider declares, derived from its own form schema. */
|
|
10
|
+
export declare function secretKeysOfProviderInfo(info: ProviderInfoLike): ReadonlySet<string>;
|
|
11
|
+
/**
|
|
12
|
+
* A copy of `config` with every declared secret replaced by the sentinel.
|
|
13
|
+
* Returns the SAME object when there is nothing to redact, so the common case
|
|
14
|
+
* (a filesystem location) allocates nothing.
|
|
15
|
+
*
|
|
16
|
+
* A key the provider declares secret but that is absent from the stored config
|
|
17
|
+
* is NOT invented — an absent password must keep reading as absent, or the
|
|
18
|
+
* wizard would show a credential where none is set and the write-back would
|
|
19
|
+
* then "keep" a value that never existed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function redactLocationConfig(config: Readonly<Record<string, unknown>>, secretKeys: ReadonlySet<string>): Readonly<Record<string, unknown>>;
|
|
22
|
+
/** The same, applied to a whole location record. */
|
|
23
|
+
export declare function redactLocation(location: StorageLocation, secretKeys: ReadonlySet<string>): StorageLocation;
|
|
24
|
+
/**
|
|
25
|
+
* Undo the redaction on the way IN: any secret key whose incoming value is the
|
|
26
|
+
* sentinel is restored from what is already stored.
|
|
27
|
+
*
|
|
28
|
+
* A sentinel with NOTHING stored behind it is dropped rather than persisted —
|
|
29
|
+
* writing the literal `__camstack_redacted__` as a password is a
|
|
30
|
+
* lock-yourself-out bug that would only surface at the next connection
|
|
31
|
+
* attempt, hours later, as an authentication failure with no explanation.
|
|
32
|
+
*/
|
|
33
|
+
export declare function restoreRedactedSecrets(incoming: Readonly<Record<string, unknown>>, stored: Readonly<Record<string, unknown>> | undefined, secretKeys: ReadonlySet<string>): Readonly<Record<string, unknown>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RelocateFootageInput, RelocateJob, RelocateMediaInput, StorageMigrationFootageMoveInput, StorageMigrationInput, StorageMigrationJob, StorageMigrationMediaMoveInput, StorageMigrationPlan, UnstampedEventMediaCount } from '@camstack/types';
|
|
1
|
+
import { RelocatableMediaCount, RelocatableMediaCountInput, RelocateFootageInput, RelocateJob, RelocateMediaInput, RelocateResidue, RelocateResidueInput, StorageMigrationDrainInput, StorageMigrationFootageMoveInput, StorageMigrationInput, StorageMigrationJob, StorageMigrationMediaMoveInput, StorageMigrationMover, StorageMigrationPlan, StorageMigrationResidue, UnstampedEventMediaCount } from '@camstack/types';
|
|
2
2
|
import { StorageOrchestratorService } from './storage-orchestrator.service.js';
|
|
3
3
|
export interface MigrationState {
|
|
4
4
|
get(): Promise<StorageMigrationJob | null>;
|
|
@@ -24,6 +24,10 @@ export interface FootageMigrationParticipant extends LeaseParticipant {
|
|
|
24
24
|
getMove(jobId: string): Promise<RelocateJob | null>;
|
|
25
25
|
cancelMove(jobId: string): Promise<boolean>;
|
|
26
26
|
refresh(leaseId: string): Promise<void>;
|
|
27
|
+
/** Every mover this engine knows about — including ones no migration armed. */
|
|
28
|
+
listMovers(): Promise<readonly RelocateJob[]>;
|
|
29
|
+
/** What a source STILL holds, from the durable hour ledger (D295). */
|
|
30
|
+
residue(input: RelocateResidueInput): Promise<RelocateResidue>;
|
|
27
31
|
}
|
|
28
32
|
export interface MediaMigrationParticipant extends LeaseParticipant {
|
|
29
33
|
startMove(input: StorageMigrationMediaMoveInput): Promise<{
|
|
@@ -41,6 +45,11 @@ export interface MediaMigrationParticipant extends LeaseParticipant {
|
|
|
41
45
|
getMove(jobId: string): Promise<RelocateJob | null>;
|
|
42
46
|
cancelMove(jobId: string): Promise<boolean>;
|
|
43
47
|
refresh(leaseId: string): Promise<void>;
|
|
48
|
+
/** Every mover this engine knows about — including ones no migration armed. */
|
|
49
|
+
listMovers(): Promise<readonly RelocateJob[]>;
|
|
50
|
+
/** How many rows a pass would still act on — the media lane's residue, from
|
|
51
|
+
* the same derivation that produces its `filesTotal`. */
|
|
52
|
+
residue(input: RelocatableMediaCountInput): Promise<RelocatableMediaCount>;
|
|
44
53
|
}
|
|
45
54
|
export interface StorageMigrationParticipants {
|
|
46
55
|
readonly pipeline: LeaseParticipant;
|
|
@@ -103,6 +112,67 @@ export declare class StorageMigrationCoordinator {
|
|
|
103
112
|
start(input: StorageMigrationInput): Promise<string>;
|
|
104
113
|
status(jobId?: string): Promise<StorageMigrationJob | null>;
|
|
105
114
|
cancel(jobId: string): Promise<boolean>;
|
|
115
|
+
/**
|
|
116
|
+
* Every mover running right now, in both lanes — including the ones no
|
|
117
|
+
* migration armed.
|
|
118
|
+
*
|
|
119
|
+
* `status` already carries a migration's own progress (the coordinator folds
|
|
120
|
+
* it onto each move from the poll it is already doing). This exists for the
|
|
121
|
+
* other half: `recording.relocateFootage` and `pipelineAnalytics.relocateMedia`
|
|
122
|
+
* are operator-callable, and until {@link drain} existed that was the only way
|
|
123
|
+
* to run a drain at all. Such a mover has no job to fold into, so without this
|
|
124
|
+
* read a five-hour operation is invisible in the UI.
|
|
125
|
+
*
|
|
126
|
+
* `migrationJobId` is best-effort by construction: the coordinator keeps ONE
|
|
127
|
+
* durable job, so a mover armed by an older, since-overwritten migration
|
|
128
|
+
* reports `null`. That is the honest answer — nothing here can still claim it.
|
|
129
|
+
*/
|
|
130
|
+
movers(): Promise<readonly StorageMigrationMover[]>;
|
|
131
|
+
/**
|
|
132
|
+
* What every class's source STILL holds — the census behind a "drain
|
|
133
|
+
* remaining" action.
|
|
134
|
+
*
|
|
135
|
+
* A class appears here only when something is (or might be) left on a
|
|
136
|
+
* location that is not its default. An empty result therefore means exactly
|
|
137
|
+
* "there is nothing to drain", which is what lets the UI offer the action
|
|
138
|
+
* only when it is true, and what lets {@link drain} refuse rather than start
|
|
139
|
+
* a job that would move nothing and report `done` — the failure mode D295
|
|
140
|
+
* exists to end.
|
|
141
|
+
*
|
|
142
|
+
* `items: null` is "the archive could not be asked" and is still listed. A
|
|
143
|
+
* residue nobody could measure is the case an operator most needs to see;
|
|
144
|
+
* dropping it because the read failed would be the quiet success again.
|
|
145
|
+
*/
|
|
146
|
+
residue(): Promise<readonly StorageMigrationResidue[]>;
|
|
147
|
+
/**
|
|
148
|
+
* Run the DRAIN half alone, against classes whose default has already moved.
|
|
149
|
+
*
|
|
150
|
+
* ## Why this is a second verb rather than a looser `start`
|
|
151
|
+
*
|
|
152
|
+
* `start` refuses a destination that is already the class's default
|
|
153
|
+
* (`"recordingsLow:ssd" is already the "recordingsLow" default`). That refusal
|
|
154
|
+
* is correct and it is load-bearing: there is genuinely nothing left to
|
|
155
|
+
* repoint, and an operator must never be able to re-repoint a migrated class
|
|
156
|
+
* by accident. Making `start` idempotent — "an already-repointed class
|
|
157
|
+
* proceeds straight to draining" — would delete that protection AND make the
|
|
158
|
+
* verb mean two different things depending on state, so the confirmation an
|
|
159
|
+
* operator reads ("pauses the writers…") would be a lie half the time.
|
|
160
|
+
*
|
|
161
|
+
* `drain` instead cannot repoint AT ALL: it never touches
|
|
162
|
+
* `setDefaultLocations`, and its job starts in `draining` with `repointed`
|
|
163
|
+
* already true, so the `repointing` / `refreshing` / `resuming` blocks of
|
|
164
|
+
* {@link run} are behind it and unreachable. The two verbs are disjoint, and
|
|
165
|
+
* `start`'s refusal keeps meaning exactly what it meant.
|
|
166
|
+
*
|
|
167
|
+
* ## Why it re-derives the work instead of resuming the old job
|
|
168
|
+
*
|
|
169
|
+
* The finished job is the audit of what happened; re-opening it destroys
|
|
170
|
+
* that. And a drain is needed in cases where no migration job ever existed
|
|
171
|
+
* (a mover armed by hand, footage stranded on a location an operator added
|
|
172
|
+
* and then un-defaulted). One job = one operation, and the work list comes
|
|
173
|
+
* from {@link residue} — the archive — not from what a previous job believed.
|
|
174
|
+
*/
|
|
175
|
+
drain(input: StorageMigrationDrainInput): Promise<string>;
|
|
106
176
|
/** Boot recovery resumes a durable unfinished state. A missing in-memory
|
|
107
177
|
* child mover is recreated from the same copy-if-absent input. */
|
|
108
178
|
recover(): Promise<void>;
|
|
@@ -15,6 +15,19 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
15
15
|
* `undefined` (treated as node-agnostic).
|
|
16
16
|
*/
|
|
17
17
|
private readonly nodeLocalByProvider;
|
|
18
|
+
/**
|
|
19
|
+
* Cached `providerId → secret config keys`, derived from each provider's own
|
|
20
|
+
* `configSchema` in the SAME refresh as `nodeLocalByProvider` — one
|
|
21
|
+
* `getProviderInfo()` round trip answers both questions.
|
|
22
|
+
*
|
|
23
|
+
* An absent providerId yields an EMPTY set, which redacts nothing. That is
|
|
24
|
+
* the one direction this cache can be wrong in, so it is worth saying why it
|
|
25
|
+
* is acceptable: the entry is populated at the same moment the provider
|
|
26
|
+
* becomes resolvable at all, so a location whose provider is unknown here
|
|
27
|
+
* cannot be dispatched to either — there is no window in which a credential
|
|
28
|
+
* is readable through a provider the orchestrator can otherwise use.
|
|
29
|
+
*/
|
|
30
|
+
private readonly secretKeysByProvider;
|
|
18
31
|
/**
|
|
19
32
|
* Disposers run on `onShutdown` — currently the eventBus subscription
|
|
20
33
|
* for `capability:provider-registered` events used by the lazy seed
|
|
@@ -61,6 +74,19 @@ export declare class StorageOrchestratorAddon extends BaseAddon<StorageOrchestra
|
|
|
61
74
|
* the recorder so disk-pressure is a single core concern.
|
|
62
75
|
*/
|
|
63
76
|
private resolveLocationThresholds;
|
|
77
|
+
/** Declared secret config keys for a provider; empty when unknown. */
|
|
78
|
+
private secretKeysFor;
|
|
79
|
+
/** A location with its provider's declared secrets replaced by the sentinel. */
|
|
80
|
+
private redacted;
|
|
81
|
+
/**
|
|
82
|
+
* Is this location backed by a provider that serves a genuine local
|
|
83
|
+
* filesystem? `true` / `false` / `undefined` — see
|
|
84
|
+
* `StorageOrchestratorService.refuseIncompatibleProvider` for why the
|
|
85
|
+
* unknown case is kept distinct rather than folded into either answer.
|
|
86
|
+
*/
|
|
87
|
+
private providerIsNodeLocal;
|
|
88
|
+
/** See the call site in the `resolve` dispatch, and `access-guards.ts`. */
|
|
89
|
+
private refuseRemoteResolve;
|
|
64
90
|
/** statfs capacity of a location's basePath, walking up to the nearest
|
|
65
91
|
* existing ancestor. Null for remote-node locations or unstattable paths. */
|
|
66
92
|
private localCapacityOf;
|