@camstack/system 1.2.443 → 1.2.445
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/assets/record-entries/icon.svg +8 -0
- package/dist/addon-runner.js +81 -42
- package/dist/addon-runner.mjs +82 -43
- package/dist/{agent-https-DlpTMDqA.js → agent-https-CiOW0-sj.js} +810 -12
- package/dist/{agent-https-U0d4uvn2.mjs → agent-https-D4Q8iFNd.mjs} +697 -13
- package/dist/auth/admin-token-manager.d.ts +9 -3
- package/dist/auth/api-key-manager.d.ts +9 -3
- package/dist/auth/auth-audit-log.d.ts +9 -3
- package/dist/auth/device-credential-manager.d.ts +5 -1
- package/dist/auth/external-identity-manager.d.ts +8 -21
- package/dist/auth/login-session-manager.d.ts +11 -3
- package/dist/auth/scoped-token-manager.d.ts +8 -52
- package/dist/auth/totp-manager.d.ts +11 -3
- package/dist/auth/user-manager.d.ts +10 -17
- 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/alert-store.d.ts +32 -0
- package/dist/builtins/alerts/alerts.addon.d.ts +19 -4
- package/dist/builtins/alerts/alerts.addon.js +331 -159
- package/dist/builtins/alerts/alerts.addon.mjs +330 -159
- package/dist/builtins/alerts/record-kinds.d.ts +15 -0
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -0
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +134 -193
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +134 -193
- package/dist/builtins/backup-orchestrator/destination-policy.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/encryption-key-store.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/record-kinds.d.ts +58 -0
- package/dist/builtins/backup-orchestrator/schedule-store.d.ts +4 -2
- package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +4 -2
- package/dist/builtins/calendars/calendar-prefs-store.d.ts +13 -5
- package/dist/builtins/calendars/calendars.addon.d.ts +2 -2
- package/dist/builtins/calendars/calendars.addon.js +67 -64
- package/dist/builtins/calendars/calendars.addon.mjs +59 -64
- package/dist/builtins/calendars/record-kinds.d.ts +18 -0
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/cluster-agent/record-kinds.d.ts +36 -0
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/block-settings-store.d.ts +8 -4
- package/dist/builtins/core-blocks/core-block-store.d.ts +8 -16
- package/dist/builtins/core-blocks/core-blocks.addon.js +85 -112
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +86 -113
- package/dist/builtins/core-blocks/index.mjs +1 -1
- package/dist/builtins/core-blocks/record-kinds.d.ts +26 -0
- package/dist/builtins/device-manager/device-manager.addon.js +111 -187
- package/dist/builtins/device-manager/device-manager.addon.mjs +110 -187
- package/dist/builtins/device-manager/device-tombstone-store.d.ts +9 -48
- package/dist/builtins/device-manager/record-kinds.d.ts +14 -0
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +152 -22
- package/dist/builtins/keychain/index.mjs +152 -22
- package/dist/builtins/keychain/keychain-service.d.ts +3 -2
- package/dist/builtins/keychain/keychain-store.d.ts +13 -2
- package/dist/builtins/keychain/record-kinds.d.ts +16 -0
- 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/auth-schema.d.ts +3 -1
- package/dist/builtins/local-auth/local-auth.addon.js +2903 -2123
- package/dist/builtins/local-auth/local-auth.addon.mjs +2904 -2124
- package/dist/builtins/local-auth/oauth-session-manager.d.ts +8 -48
- package/dist/builtins/local-auth/record-kinds.d.ts +141 -0
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- 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/record-entries/entries-service.d.ts +42 -0
- package/dist/builtins/record-entries/index.d.ts +1 -0
- package/dist/builtins/record-entries/index.js +142 -0
- package/dist/builtins/record-entries/index.mjs +136 -0
- package/dist/builtins/record-entries/record-entries.addon.d.ts +13 -0
- package/dist/builtins/records/legacy-table-row-count.d.ts +5 -0
- package/dist/builtins/records/phase6-declare-gate.d.ts +28 -0
- package/dist/builtins/records-isolated.d.ts +10 -0
- 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/file-host-client.d.ts +2 -0
- package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +4 -0
- package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +7 -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/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/integration-record-kinds.d.ts +30 -0
- package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -16
- package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +7 -0
- package/dist/builtins/sqlite-storage/placement-router.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +5 -0
- package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +6 -0
- package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +29 -0
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +51 -0
- package/dist/builtins/sqlite-storage/records/records-engine.d.ts +94 -0
- package/dist/builtins/sqlite-storage/records/records-explain.d.ts +18 -0
- package/dist/builtins/sqlite-storage/records/records-plan.d.ts +90 -0
- package/dist/builtins/sqlite-storage/records/records-probe.d.ts +33 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +63 -0
- package/dist/builtins/sqlite-storage/records/records-rows.d.ts +46 -0
- package/dist/builtins/sqlite-storage/records/records-sql.d.ts +41 -0
- package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +17 -10
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +446 -5
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +446 -5
- package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +15 -1
- package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +5 -2
- package/dist/builtins/storage-orchestrator/location-store.d.ts +7 -2
- package/dist/builtins/storage-orchestrator/record-kinds.d.ts +38 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +196 -5
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +195 -6
- package/dist/builtins/system-config/record-kinds.d.ts +32 -0
- package/dist/builtins/system-config/system-config.addon.js +53 -618
- package/dist/builtins/system-config/system-config.addon.mjs +29 -577
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-C8tUG2uL.mjs → composition-sources-BMt5cFYb.mjs} +1 -1
- package/dist/{composition-sources-BUXX1e8j.js → composition-sources-D3fi9Xns.js} +1 -1
- package/dist/{constants-CGwVaAV3.mjs → constants-BMHCxRzb.mjs} +1 -1
- package/dist/{constants-DWmm7_of.js → constants-Br879Axi.js} +1 -1
- package/dist/{device-ca-DGayRmC0.js → device-ca-CnJ_va7i.js} +1 -1
- package/dist/{device-ca-DBfiJ_SB.mjs → device-ca-T8osSMos.mjs} +1 -1
- package/dist/{dist-Bxt_S-9a.mjs → dist-BNunRyXT.mjs} +1133 -93
- package/dist/{dist-D9qT3jHr.js → dist-DgOG8flk.js} +1354 -92
- package/dist/file-host-worker.js +11 -1
- package/dist/file-host-worker.mjs +11 -1
- package/dist/{hub-mdns-ciao-B-wk9nzx.js → hub-mdns-ciao-BIkTHq-n.js} +2 -2
- package/dist/{hub-mdns-ciao-DpPcQDg-.mjs → hub-mdns-ciao-D16oRQ9K.mjs} +2 -2
- package/dist/index.d.ts +7 -0
- package/dist/index.js +3111 -2806
- package/dist/index.mjs +3083 -2795
- package/dist/kernel/index.d.ts +2 -0
- package/dist/kernel/moleculer/event-bus.d.ts +3 -1
- package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +5 -1
- package/dist/kernel/moleculer/records-api-transport.d.ts +9 -0
- package/dist/kernel/moleculer/remote-logger.d.ts +2 -2
- package/dist/kernel/settings-view-types.d.ts +0 -7
- package/dist/kernel/transport/cap-route-resolver.d.ts +9 -38
- package/dist/phase6-declare-gate-Ci1-8uUn.js +98 -0
- package/dist/phase6-declare-gate-tkKOEitw.mjs +93 -0
- package/dist/read-all-rows-CVoO1ONM.js +29 -0
- package/dist/read-all-rows-TaPqdWNF.mjs +25 -0
- package/dist/records/read-all-rows.d.ts +6 -0
- package/dist/{restore-archive-9CGgeBzD.mjs → restore-archive-DR9MtO7J.mjs} +339 -9
- package/dist/{restore-archive-BMNXwWWD.js → restore-archive-DjJnCgap.js} +353 -5
- package/dist/tls/agent-https-names.d.ts +9 -13
- package/dist/{wal-maintenance-cRHR4rUY.js → wal-maintenance-CODGqhKY.js} +0 -0
- package/dist/{wal-maintenance-sIB32ONp.mjs → wal-maintenance-CfvgtQ7C.mjs} +0 -0
- package/package.json +22 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record kinds owned by core-blocks (phase 4).
|
|
3
|
+
*/
|
|
4
|
+
import { type DefinedRecordKind } from "@camstack/types";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
export declare const CORE_BLOCKS_COLLECTION = "core_blocks";
|
|
7
|
+
export declare const CORE_BLOCK_SETTINGS_COLLECTION = "core-blocks:settings";
|
|
8
|
+
export type CoreBlockRowBody = {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly enabled: boolean;
|
|
11
|
+
readonly placement: string;
|
|
12
|
+
readonly updatedAt: number;
|
|
13
|
+
readonly block: Record<string, unknown>;
|
|
14
|
+
};
|
|
15
|
+
export declare const CoreBlockRowBodySchema: z.ZodType<CoreBlockRowBody>;
|
|
16
|
+
export type CoreBlockSettingsBody = {
|
|
17
|
+
readonly values: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
export declare const CoreBlockSettingsBodySchema: z.ZodType<CoreBlockSettingsBody>;
|
|
20
|
+
export type CoreBlocksRecordKindsMap = {
|
|
21
|
+
readonly blocks: DefinedRecordKind<z.ZodType<CoreBlockRowBody>>;
|
|
22
|
+
readonly settings: DefinedRecordKind<z.ZodType<CoreBlockSettingsBody>>;
|
|
23
|
+
};
|
|
24
|
+
export declare const coreBlocksRecordKinds: CoreBlocksRecordKindsMap;
|
|
25
|
+
export declare const coreBlocksBlocksRecordKind: DefinedRecordKind<z.ZodType<CoreBlockRowBody>>;
|
|
26
|
+
export declare const coreBlocksSettingsRecordKind: DefinedRecordKind<z.ZodType<CoreBlockSettingsBody>>;
|
|
@@ -3,7 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-DgOG8flk.js");
|
|
7
|
+
const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
|
|
7
8
|
const require_prefix_range = require("../../prefix-range-D_KueXbQ.js");
|
|
8
9
|
const require_prefix_walk = require("../../prefix-walk-Dv6MLZlM.js");
|
|
9
10
|
const require_retired_settings_keys = require("../../retired-settings-keys-D_VwZiDt.js");
|
|
@@ -1100,6 +1101,10 @@ function mergeAggregates(parts) {
|
|
|
1100
1101
|
function isRecord$2(value) {
|
|
1101
1102
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1102
1103
|
}
|
|
1104
|
+
function isConfigFieldWithValue(field) {
|
|
1105
|
+
if (!isRecord$2(field)) return false;
|
|
1106
|
+
return typeof field.type === "string" && typeof field.key === "string" && "value" in field;
|
|
1107
|
+
}
|
|
1103
1108
|
/** The declared paths that name a top-level config key. */
|
|
1104
1109
|
function topLevelKeys(paths) {
|
|
1105
1110
|
return new Set(paths.filter((p) => p.length > 0 && !p.includes(".") && !p.includes("[")));
|
|
@@ -1119,8 +1124,8 @@ function viewField(field, stored, declared) {
|
|
|
1119
1124
|
fields: tab["fields"].map((f) => viewField(f, stored, declared))
|
|
1120
1125
|
} : tab)
|
|
1121
1126
|
};
|
|
1122
|
-
|
|
1123
|
-
|
|
1127
|
+
if (!isConfigFieldWithValue(field)) return field;
|
|
1128
|
+
const key = field.key;
|
|
1124
1129
|
const marker = stored[key];
|
|
1125
1130
|
if (!require_dist.isSecretMarker(marker)) return field;
|
|
1126
1131
|
const secretByType = require_dist.isKeychainStoredField(field);
|
|
@@ -7873,6 +7878,105 @@ var DeviceMetaStore = class {
|
|
|
7873
7878
|
});
|
|
7874
7879
|
};
|
|
7875
7880
|
//#endregion
|
|
7881
|
+
//#region src/builtins/device-manager/record-kinds.ts
|
|
7882
|
+
var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
|
|
7883
|
+
var DeviceTombstoneBodySchema = require_dist.DeviceTombstoneSchema.omit({ deviceId: true });
|
|
7884
|
+
var _deviceManagerRecordKinds = require_dist.defineRecordKinds({ tombstones: {
|
|
7885
|
+
schema: DeviceTombstoneBodySchema,
|
|
7886
|
+
class: "ledger",
|
|
7887
|
+
writeTrigger: "`removeDevice` records one row per deleted device after the device row is gone; re-record keeps the earlier `deletedAt`",
|
|
7888
|
+
device: "none",
|
|
7889
|
+
at: "required",
|
|
7890
|
+
indexes: [{
|
|
7891
|
+
name: "deleted_at",
|
|
7892
|
+
fields: ["deletedAt"]
|
|
7893
|
+
}],
|
|
7894
|
+
retention: {
|
|
7895
|
+
owner: "device-manager",
|
|
7896
|
+
reason: "90 days (`DEVICE_TOMBSTONE_RETENTION_MS`), pruned whenever a tombstone is written or the list is read"
|
|
7897
|
+
},
|
|
7898
|
+
adoptsFrom: DEVICE_TOMBSTONES_COLLECTION
|
|
7899
|
+
} });
|
|
7900
|
+
var deviceManagerRecordKinds = _deviceManagerRecordKinds;
|
|
7901
|
+
_deviceManagerRecordKinds.tombstones;
|
|
7902
|
+
//#endregion
|
|
7903
|
+
//#region src/builtins/device-manager/device-tombstone-store.ts
|
|
7904
|
+
/**
|
|
7905
|
+
* The tombstones of deleted devices (D865) — `tombstones` record kind (phase 4).
|
|
7906
|
+
*/
|
|
7907
|
+
var DEVICE_TOMBSTONES_COLLECTION = "device-manager:tombstones";
|
|
7908
|
+
/** More than the engine's default row cap, so a read is never silently truncated. */
|
|
7909
|
+
var TOMBSTONE_READ_LIMIT = 2e4;
|
|
7910
|
+
function rowToTombstone(id, body) {
|
|
7911
|
+
const deviceId = Number(id);
|
|
7912
|
+
if (!Number.isInteger(deviceId) || deviceId <= 0) return null;
|
|
7913
|
+
return {
|
|
7914
|
+
deviceId,
|
|
7915
|
+
deletedAt: body.deletedAt,
|
|
7916
|
+
providerAddonId: body.providerAddonId
|
|
7917
|
+
};
|
|
7918
|
+
}
|
|
7919
|
+
var DeviceTombstoneStore = class DeviceTombstoneStore {
|
|
7920
|
+
kind;
|
|
7921
|
+
logger;
|
|
7922
|
+
now;
|
|
7923
|
+
retentionMs;
|
|
7924
|
+
constructor(opts) {
|
|
7925
|
+
this.kind = opts.kind;
|
|
7926
|
+
this.logger = opts.logger;
|
|
7927
|
+
this.now = opts.now ?? (() => Date.now());
|
|
7928
|
+
this.retentionMs = opts.retentionMs ?? 7776e6;
|
|
7929
|
+
}
|
|
7930
|
+
static of(records, logger) {
|
|
7931
|
+
return new DeviceTombstoneStore({
|
|
7932
|
+
kind: records.kind(deviceManagerRecordKinds.tombstones),
|
|
7933
|
+
logger
|
|
7934
|
+
});
|
|
7935
|
+
}
|
|
7936
|
+
/** Record a deletion. Re-recording the same id keeps the EARLIER `deletedAt`. */
|
|
7937
|
+
async record(tombstone) {
|
|
7938
|
+
const key = String(tombstone.deviceId);
|
|
7939
|
+
const existing = await this.kind.get(key);
|
|
7940
|
+
if ((existing !== null ? rowToTombstone(existing.id, existing.data)?.deletedAt : void 0) === void 0) await this.kind.put({
|
|
7941
|
+
id: key,
|
|
7942
|
+
at: tombstone.deletedAt,
|
|
7943
|
+
data: {
|
|
7944
|
+
deletedAt: tombstone.deletedAt,
|
|
7945
|
+
providerAddonId: tombstone.providerAddonId
|
|
7946
|
+
}
|
|
7947
|
+
});
|
|
7948
|
+
await this.pruneExpired();
|
|
7949
|
+
}
|
|
7950
|
+
/** Tombstones with `deletedAt >= sinceMs`, oldest first. Expired ones are pruned first. */
|
|
7951
|
+
async listSince(sinceMs) {
|
|
7952
|
+
await this.pruneExpired();
|
|
7953
|
+
const floor = Math.max(sinceMs, this.now() - this.retentionMs);
|
|
7954
|
+
const rows = await (0, import_read_all_rows.readAllRows)(this.kind, {
|
|
7955
|
+
atFrom: floor,
|
|
7956
|
+
order: "at"
|
|
7957
|
+
});
|
|
7958
|
+
const out = [];
|
|
7959
|
+
for (const row of rows) {
|
|
7960
|
+
if (out.length >= TOMBSTONE_READ_LIMIT) break;
|
|
7961
|
+
const decoded = rowToTombstone(row.id, row.data);
|
|
7962
|
+
if (decoded !== null && decoded.deletedAt >= floor) out.push(decoded);
|
|
7963
|
+
}
|
|
7964
|
+
return out;
|
|
7965
|
+
}
|
|
7966
|
+
/** Delete tombstones older than the retention window. Best-effort: a failure is logged. */
|
|
7967
|
+
async pruneExpired() {
|
|
7968
|
+
try {
|
|
7969
|
+
const cutoff = this.now() - this.retentionMs;
|
|
7970
|
+
const rows = await (0, import_read_all_rows.readAllRows)(this.kind, { atTo: cutoff - 1 });
|
|
7971
|
+
for (const row of rows) await this.kind.delete(row.id);
|
|
7972
|
+
return rows.length;
|
|
7973
|
+
} catch (err) {
|
|
7974
|
+
this.logger.warn("device tombstone prune failed — retried on the next write", { meta: { error: require_dist.errMsg(err) } });
|
|
7975
|
+
return 0;
|
|
7976
|
+
}
|
|
7977
|
+
}
|
|
7978
|
+
};
|
|
7979
|
+
//#endregion
|
|
7876
7980
|
//#region src/builtins/device-manager/fleet-read-census.ts
|
|
7877
7981
|
/** How many stack frames identify a call site. One frame is a method; three are
|
|
7878
7982
|
* a cause — `listFleet < listAll < onDeviceRegistered` is the answer, `listAll`
|
|
@@ -8774,181 +8878,6 @@ var DeviceRowStore = class {
|
|
|
8774
8878
|
}
|
|
8775
8879
|
};
|
|
8776
8880
|
//#endregion
|
|
8777
|
-
//#region src/builtins/device-manager/device-tombstone-store.ts
|
|
8778
|
-
/**
|
|
8779
|
-
* The tombstones of deleted devices (D865).
|
|
8780
|
-
*
|
|
8781
|
-
* A device DELETE is a fact other addons must be able to learn reliably, long
|
|
8782
|
-
* after the `DeviceUnregistered` event (telemetry, droppable — D8/D11) is gone.
|
|
8783
|
-
* device-manager is the only authority on whether a device exists, so the record
|
|
8784
|
-
* of a deletion lives here, in its own collection, beside the device ledger.
|
|
8785
|
-
*
|
|
8786
|
-
* ## What a tombstone is NOT
|
|
8787
|
-
*
|
|
8788
|
-
* It is not "the device is unregistered / offline / its provider is restarting".
|
|
8789
|
-
* Those are states of a device that still exists; only {@link record}'s one
|
|
8790
|
-
* caller — `removeDevice`, the single door every delete converges on — writes a
|
|
8791
|
-
* tombstone. Anything that reconciles from tombstones therefore can never
|
|
8792
|
-
* destroy data of a device that merely went quiet.
|
|
8793
|
-
*
|
|
8794
|
-
* ## Expiry
|
|
8795
|
-
*
|
|
8796
|
-
* {@link DEVICE_TOMBSTONE_RETENTION_MS} (90 days). A tombstone older than that
|
|
8797
|
-
* is deleted the next time one is written or read. Ninety days is generous on
|
|
8798
|
-
* purpose: an addon that stayed disabled for a quarter still learns of the
|
|
8799
|
-
* deletions on its return. Data of a device deleted longer ago than that is
|
|
8800
|
-
* reachable only by the admin "clean data of deleted devices" action.
|
|
8801
|
-
*/
|
|
8802
|
-
/**
|
|
8803
|
-
* @durable class=ledger owner=device-manager
|
|
8804
|
-
* write="`removeDevice` records one row per deleted device (key = device id) after the
|
|
8805
|
-
* device row is gone"
|
|
8806
|
-
* retention="90 days (`DEVICE_TOMBSTONE_RETENTION_MS`), pruned whenever a tombstone is
|
|
8807
|
-
* written or the list is read. Bounded by the deletions an operator makes in a quarter."
|
|
8808
|
-
*/
|
|
8809
|
-
var DEVICE_TOMBSTONES_COLLECTION = "device-manager:tombstones";
|
|
8810
|
-
var DEVICE_TOMBSTONE_COLUMNS = [
|
|
8811
|
-
{
|
|
8812
|
-
name: "id",
|
|
8813
|
-
type: "TEXT",
|
|
8814
|
-
primaryKey: true,
|
|
8815
|
-
notNull: true
|
|
8816
|
-
},
|
|
8817
|
-
{
|
|
8818
|
-
name: "deviceId",
|
|
8819
|
-
type: "INTEGER",
|
|
8820
|
-
notNull: true
|
|
8821
|
-
},
|
|
8822
|
-
{
|
|
8823
|
-
name: "deletedAt",
|
|
8824
|
-
type: "INTEGER",
|
|
8825
|
-
notNull: true
|
|
8826
|
-
},
|
|
8827
|
-
{
|
|
8828
|
-
name: "providerAddonId",
|
|
8829
|
-
type: "TEXT",
|
|
8830
|
-
notNull: true
|
|
8831
|
-
}
|
|
8832
|
-
];
|
|
8833
|
-
var DEVICE_TOMBSTONE_INDEXES = [{
|
|
8834
|
-
name: "idx_dm_tombstones_deleted_at",
|
|
8835
|
-
columns: ["deletedAt"]
|
|
8836
|
-
}];
|
|
8837
|
-
/** More than the engine's default row cap, so a read is never silently truncated. */
|
|
8838
|
-
var TOMBSTONE_READ_LIMIT = 2e4;
|
|
8839
|
-
function decodeTombstone(raw) {
|
|
8840
|
-
const deviceId = raw["deviceId"];
|
|
8841
|
-
const deletedAt = raw["deletedAt"];
|
|
8842
|
-
const providerAddonId = raw["providerAddonId"];
|
|
8843
|
-
if (typeof deviceId !== "number" || !Number.isInteger(deviceId) || deviceId <= 0) return null;
|
|
8844
|
-
if (typeof deletedAt !== "number" || typeof providerAddonId !== "string") return null;
|
|
8845
|
-
return {
|
|
8846
|
-
deviceId,
|
|
8847
|
-
deletedAt,
|
|
8848
|
-
providerAddonId
|
|
8849
|
-
};
|
|
8850
|
-
}
|
|
8851
|
-
var DeviceTombstoneStore = class {
|
|
8852
|
-
backend;
|
|
8853
|
-
logger;
|
|
8854
|
-
now;
|
|
8855
|
-
retentionMs;
|
|
8856
|
-
declared = null;
|
|
8857
|
-
constructor(opts) {
|
|
8858
|
-
this.backend = opts.backend;
|
|
8859
|
-
this.logger = opts.logger;
|
|
8860
|
-
this.now = opts.now ?? (() => Date.now());
|
|
8861
|
-
this.retentionMs = opts.retentionMs ?? 7776e6;
|
|
8862
|
-
}
|
|
8863
|
-
/**
|
|
8864
|
-
* Declare the collection now. Idempotent; a rejection is not latched.
|
|
8865
|
-
*
|
|
8866
|
-
* Called at device-manager init (D871) so the table exists on a hub that has
|
|
8867
|
-
* not deleted a device yet. It used to be declared only by the first
|
|
8868
|
-
* `record` / `listSince`, i.e. by the first delete or by an implementer's
|
|
8869
|
-
* reconcile — so a hub whose implementers had not been redeployed, and where
|
|
8870
|
-
* nothing was deleted, never had the table, and the census read that as
|
|
8871
|
-
* "D865 is not running". A DECLARATION only: nothing is read, written or
|
|
8872
|
-
* purged here.
|
|
8873
|
-
*/
|
|
8874
|
-
declare() {
|
|
8875
|
-
if (this.declared !== null) return this.declared;
|
|
8876
|
-
const run = this.backend.declareCollection({
|
|
8877
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8878
|
-
columns: DEVICE_TOMBSTONE_COLUMNS,
|
|
8879
|
-
indexes: DEVICE_TOMBSTONE_INDEXES
|
|
8880
|
-
}).catch((err) => {
|
|
8881
|
-
this.declared = null;
|
|
8882
|
-
throw err;
|
|
8883
|
-
});
|
|
8884
|
-
this.declared = run;
|
|
8885
|
-
return run;
|
|
8886
|
-
}
|
|
8887
|
-
/** Record a deletion. Re-recording the same id keeps the EARLIER `deletedAt`. */
|
|
8888
|
-
async record(tombstone) {
|
|
8889
|
-
await this.declare();
|
|
8890
|
-
const key = String(tombstone.deviceId);
|
|
8891
|
-
const existing = await this.backend.get({
|
|
8892
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8893
|
-
key
|
|
8894
|
-
});
|
|
8895
|
-
if ((isPlainObject(existing) ? decodeTombstone(existing) : null) === null) await this.backend.set({
|
|
8896
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8897
|
-
key,
|
|
8898
|
-
value: {
|
|
8899
|
-
deviceId: tombstone.deviceId,
|
|
8900
|
-
deletedAt: tombstone.deletedAt,
|
|
8901
|
-
providerAddonId: tombstone.providerAddonId
|
|
8902
|
-
}
|
|
8903
|
-
});
|
|
8904
|
-
await this.pruneExpired();
|
|
8905
|
-
}
|
|
8906
|
-
/** Tombstones with `deletedAt >= sinceMs`, oldest first. Expired ones are pruned first. */
|
|
8907
|
-
async listSince(sinceMs) {
|
|
8908
|
-
await this.declare();
|
|
8909
|
-
await this.pruneExpired();
|
|
8910
|
-
const floor = Math.max(sinceMs, this.now() - this.retentionMs);
|
|
8911
|
-
const rows = await this.backend.query({
|
|
8912
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8913
|
-
filter: {
|
|
8914
|
-
whereBetween: { deletedAt: [floor, Number.MAX_SAFE_INTEGER] },
|
|
8915
|
-
orderBy: {
|
|
8916
|
-
field: "deletedAt",
|
|
8917
|
-
direction: "asc"
|
|
8918
|
-
},
|
|
8919
|
-
limit: TOMBSTONE_READ_LIMIT
|
|
8920
|
-
}
|
|
8921
|
-
});
|
|
8922
|
-
const out = [];
|
|
8923
|
-
for (const row of rows) {
|
|
8924
|
-
const decoded = decodeTombstone(row.data);
|
|
8925
|
-
if (decoded !== null) out.push(decoded);
|
|
8926
|
-
}
|
|
8927
|
-
return out;
|
|
8928
|
-
}
|
|
8929
|
-
/** Delete tombstones older than the retention window. Best-effort: a failure is logged. */
|
|
8930
|
-
async pruneExpired() {
|
|
8931
|
-
try {
|
|
8932
|
-
const cutoff = this.now() - this.retentionMs;
|
|
8933
|
-
const stale = await this.backend.query({
|
|
8934
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8935
|
-
filter: {
|
|
8936
|
-
whereBetween: { deletedAt: [0, cutoff - 1] },
|
|
8937
|
-
limit: TOMBSTONE_READ_LIMIT
|
|
8938
|
-
}
|
|
8939
|
-
});
|
|
8940
|
-
for (const row of stale) await this.backend.delete({
|
|
8941
|
-
collection: DEVICE_TOMBSTONES_COLLECTION,
|
|
8942
|
-
key: row.id
|
|
8943
|
-
});
|
|
8944
|
-
return stale.length;
|
|
8945
|
-
} catch (err) {
|
|
8946
|
-
this.logger.warn("device tombstone prune failed — retried on the next write", { meta: { error: require_dist.errMsg(err) } });
|
|
8947
|
-
return 0;
|
|
8948
|
-
}
|
|
8949
|
-
}
|
|
8950
|
-
};
|
|
8951
|
-
//#endregion
|
|
8952
8881
|
//#region src/builtins/device-manager/device-state-claims.ts
|
|
8953
8882
|
function createDeviceStateClaimMethods(deps) {
|
|
8954
8883
|
const { mirror, index, settings, logger } = deps;
|
|
@@ -10864,15 +10793,10 @@ var DeviceManagerAddon = class extends require_dist.BaseAddon {
|
|
|
10864
10793
|
const deviceRows = new DeviceRowStore(deviceRowBackendOf(settingsStoreApi), this.ctx.logger.child("rows"));
|
|
10865
10794
|
await deviceRows.declare();
|
|
10866
10795
|
this.deviceRows = deviceRows;
|
|
10867
|
-
const
|
|
10868
|
-
|
|
10869
|
-
|
|
10870
|
-
|
|
10871
|
-
try {
|
|
10872
|
-
await tombstones.declare();
|
|
10873
|
-
} catch (err) {
|
|
10874
|
-
this.ctx.logger.warn("device tombstones collection not declared at init — retried on first use", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
10875
|
-
}
|
|
10796
|
+
const records = this.ctx.records;
|
|
10797
|
+
if (records === void 0) throw new Error("[device-manager] ctx.records is required on the hub");
|
|
10798
|
+
await records.declare(deviceManagerRecordKinds);
|
|
10799
|
+
const tombstones = DeviceTombstoneStore.of(records, this.ctx.logger.child("tombstones"));
|
|
10876
10800
|
this.staleWrapperActivations.checkOnce(() => readBindingsStore(this.bindingsDeps));
|
|
10877
10801
|
try {
|
|
10878
10802
|
await require_retired_settings_keys.purgeRetiredSettingsRows(deviceRows.retiredRowStore(), this.ctx.logger.child("RetiredRows"));
|