@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.
Files changed (160) hide show
  1. package/assets/record-entries/icon.svg +8 -0
  2. package/dist/addon-runner.js +81 -42
  3. package/dist/addon-runner.mjs +82 -43
  4. package/dist/{agent-https-DlpTMDqA.js → agent-https-CiOW0-sj.js} +810 -12
  5. package/dist/{agent-https-U0d4uvn2.mjs → agent-https-D4Q8iFNd.mjs} +697 -13
  6. package/dist/auth/admin-token-manager.d.ts +9 -3
  7. package/dist/auth/api-key-manager.d.ts +9 -3
  8. package/dist/auth/auth-audit-log.d.ts +9 -3
  9. package/dist/auth/device-credential-manager.d.ts +5 -1
  10. package/dist/auth/external-identity-manager.d.ts +8 -21
  11. package/dist/auth/login-session-manager.d.ts +11 -3
  12. package/dist/auth/scoped-token-manager.d.ts +8 -52
  13. package/dist/auth/totp-manager.d.ts +11 -3
  14. package/dist/auth/user-manager.d.ts +10 -17
  15. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  16. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  17. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  18. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  19. package/dist/builtins/alerts/alert-store.d.ts +32 -0
  20. package/dist/builtins/alerts/alerts.addon.d.ts +19 -4
  21. package/dist/builtins/alerts/alerts.addon.js +331 -159
  22. package/dist/builtins/alerts/alerts.addon.mjs +330 -159
  23. package/dist/builtins/alerts/record-kinds.d.ts +15 -0
  24. package/dist/builtins/autotrack/index.js +1 -1
  25. package/dist/builtins/autotrack/index.mjs +1 -1
  26. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.d.ts +1 -0
  27. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +134 -193
  28. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +134 -193
  29. package/dist/builtins/backup-orchestrator/destination-policy.d.ts +4 -2
  30. package/dist/builtins/backup-orchestrator/encryption-key-store.d.ts +4 -2
  31. package/dist/builtins/backup-orchestrator/record-kinds.d.ts +58 -0
  32. package/dist/builtins/backup-orchestrator/schedule-store.d.ts +4 -2
  33. package/dist/builtins/backup-orchestrator/seed-marker-store.d.ts +4 -2
  34. package/dist/builtins/calendars/calendar-prefs-store.d.ts +13 -5
  35. package/dist/builtins/calendars/calendars.addon.d.ts +2 -2
  36. package/dist/builtins/calendars/calendars.addon.js +67 -64
  37. package/dist/builtins/calendars/calendars.addon.mjs +59 -64
  38. package/dist/builtins/calendars/record-kinds.d.ts +18 -0
  39. package/dist/builtins/camera-grid/index.js +1 -1
  40. package/dist/builtins/camera-grid/index.mjs +1 -1
  41. package/dist/builtins/cluster-agent/record-kinds.d.ts +36 -0
  42. package/dist/builtins/composer/composer.addon.js +2 -2
  43. package/dist/builtins/composer/composer.addon.mjs +2 -2
  44. package/dist/builtins/console-logging/index.js +1 -1
  45. package/dist/builtins/console-logging/index.mjs +1 -1
  46. package/dist/builtins/core-blocks/block-settings-store.d.ts +8 -4
  47. package/dist/builtins/core-blocks/core-block-store.d.ts +8 -16
  48. package/dist/builtins/core-blocks/core-blocks.addon.js +85 -112
  49. package/dist/builtins/core-blocks/core-blocks.addon.mjs +86 -113
  50. package/dist/builtins/core-blocks/index.mjs +1 -1
  51. package/dist/builtins/core-blocks/record-kinds.d.ts +26 -0
  52. package/dist/builtins/device-manager/device-manager.addon.js +111 -187
  53. package/dist/builtins/device-manager/device-manager.addon.mjs +110 -187
  54. package/dist/builtins/device-manager/device-tombstone-store.d.ts +9 -48
  55. package/dist/builtins/device-manager/record-kinds.d.ts +14 -0
  56. package/dist/builtins/hub-forwarder/index.js +1 -1
  57. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  58. package/dist/builtins/keychain/index.js +152 -22
  59. package/dist/builtins/keychain/index.mjs +152 -22
  60. package/dist/builtins/keychain/keychain-service.d.ts +3 -2
  61. package/dist/builtins/keychain/keychain-store.d.ts +13 -2
  62. package/dist/builtins/keychain/record-kinds.d.ts +16 -0
  63. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  64. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  65. package/dist/builtins/local-auth/auth-schema.d.ts +3 -1
  66. package/dist/builtins/local-auth/local-auth.addon.js +2903 -2123
  67. package/dist/builtins/local-auth/local-auth.addon.mjs +2904 -2124
  68. package/dist/builtins/local-auth/oauth-session-manager.d.ts +8 -48
  69. package/dist/builtins/local-auth/record-kinds.d.ts +141 -0
  70. package/dist/builtins/local-network/local-network.addon.js +2 -2
  71. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  72. package/dist/builtins/loki-logging/index.js +1 -1
  73. package/dist/builtins/loki-logging/index.mjs +1 -1
  74. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  75. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  76. package/dist/builtins/platform-probe/index.js +1 -1
  77. package/dist/builtins/platform-probe/index.mjs +1 -1
  78. package/dist/builtins/record-entries/entries-service.d.ts +42 -0
  79. package/dist/builtins/record-entries/index.d.ts +1 -0
  80. package/dist/builtins/record-entries/index.js +142 -0
  81. package/dist/builtins/record-entries/index.mjs +136 -0
  82. package/dist/builtins/record-entries/record-entries.addon.d.ts +13 -0
  83. package/dist/builtins/records/legacy-table-row-count.d.ts +5 -0
  84. package/dist/builtins/records/phase6-declare-gate.d.ts +28 -0
  85. package/dist/builtins/records-isolated.d.ts +10 -0
  86. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  87. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  88. package/dist/builtins/snapshot/index.js +1 -1
  89. package/dist/builtins/snapshot/index.mjs +1 -1
  90. package/dist/builtins/sqlite-storage/file-host-client.d.ts +2 -0
  91. package/dist/builtins/sqlite-storage/file-host-handlers.d.ts +4 -0
  92. package/dist/builtins/sqlite-storage/file-host-protocol.d.ts +7 -1
  93. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  94. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  95. package/dist/builtins/sqlite-storage/index.js +1 -1
  96. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  97. package/dist/builtins/sqlite-storage/integration-record-kinds.d.ts +30 -0
  98. package/dist/builtins/sqlite-storage/integration-registry.d.ts +10 -16
  99. package/dist/builtins/sqlite-storage/owned-sqlite-file.d.ts +7 -0
  100. package/dist/builtins/sqlite-storage/placement-router.d.ts +5 -0
  101. package/dist/builtins/sqlite-storage/records/count-settings-array-legacy.d.ts +5 -0
  102. package/dist/builtins/sqlite-storage/records/count-settings-brokers-legacy.d.ts +6 -0
  103. package/dist/builtins/sqlite-storage/records/records-catalog.d.ts +29 -0
  104. package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +51 -0
  105. package/dist/builtins/sqlite-storage/records/records-engine.d.ts +94 -0
  106. package/dist/builtins/sqlite-storage/records/records-explain.d.ts +18 -0
  107. package/dist/builtins/sqlite-storage/records/records-plan.d.ts +90 -0
  108. package/dist/builtins/sqlite-storage/records/records-probe.d.ts +33 -0
  109. package/dist/builtins/sqlite-storage/records/records-provider.d.ts +63 -0
  110. package/dist/builtins/sqlite-storage/records/records-rows.d.ts +46 -0
  111. package/dist/builtins/sqlite-storage/records/records-sql.d.ts +41 -0
  112. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +17 -10
  113. package/dist/builtins/sqlite-storage/sqlite-settings.addon.d.ts +8 -0
  114. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +446 -5
  115. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +446 -5
  116. package/dist/builtins/sqlite-storage/storage-admin-provider.d.ts +15 -1
  117. package/dist/builtins/storage-orchestrator/drain-state-store.d.ts +5 -2
  118. package/dist/builtins/storage-orchestrator/location-store.d.ts +7 -2
  119. package/dist/builtins/storage-orchestrator/record-kinds.d.ts +38 -0
  120. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +2 -0
  121. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +196 -5
  122. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +195 -6
  123. package/dist/builtins/system-config/record-kinds.d.ts +32 -0
  124. package/dist/builtins/system-config/system-config.addon.js +53 -618
  125. package/dist/builtins/system-config/system-config.addon.mjs +29 -577
  126. package/dist/builtins/winston-logging/index.js +1 -1
  127. package/dist/builtins/winston-logging/index.mjs +1 -1
  128. package/dist/{composition-sources-C8tUG2uL.mjs → composition-sources-BMt5cFYb.mjs} +1 -1
  129. package/dist/{composition-sources-BUXX1e8j.js → composition-sources-D3fi9Xns.js} +1 -1
  130. package/dist/{constants-CGwVaAV3.mjs → constants-BMHCxRzb.mjs} +1 -1
  131. package/dist/{constants-DWmm7_of.js → constants-Br879Axi.js} +1 -1
  132. package/dist/{device-ca-DGayRmC0.js → device-ca-CnJ_va7i.js} +1 -1
  133. package/dist/{device-ca-DBfiJ_SB.mjs → device-ca-T8osSMos.mjs} +1 -1
  134. package/dist/{dist-Bxt_S-9a.mjs → dist-BNunRyXT.mjs} +1133 -93
  135. package/dist/{dist-D9qT3jHr.js → dist-DgOG8flk.js} +1354 -92
  136. package/dist/file-host-worker.js +11 -1
  137. package/dist/file-host-worker.mjs +11 -1
  138. package/dist/{hub-mdns-ciao-B-wk9nzx.js → hub-mdns-ciao-BIkTHq-n.js} +2 -2
  139. package/dist/{hub-mdns-ciao-DpPcQDg-.mjs → hub-mdns-ciao-D16oRQ9K.mjs} +2 -2
  140. package/dist/index.d.ts +7 -0
  141. package/dist/index.js +3111 -2806
  142. package/dist/index.mjs +3083 -2795
  143. package/dist/kernel/index.d.ts +2 -0
  144. package/dist/kernel/moleculer/event-bus.d.ts +3 -1
  145. package/dist/kernel/moleculer/mesh-mtls/mesh-certificate-registry.d.ts +5 -1
  146. package/dist/kernel/moleculer/records-api-transport.d.ts +9 -0
  147. package/dist/kernel/moleculer/remote-logger.d.ts +2 -2
  148. package/dist/kernel/settings-view-types.d.ts +0 -7
  149. package/dist/kernel/transport/cap-route-resolver.d.ts +9 -38
  150. package/dist/phase6-declare-gate-Ci1-8uUn.js +98 -0
  151. package/dist/phase6-declare-gate-tkKOEitw.mjs +93 -0
  152. package/dist/read-all-rows-CVoO1ONM.js +29 -0
  153. package/dist/read-all-rows-TaPqdWNF.mjs +25 -0
  154. package/dist/records/read-all-rows.d.ts +6 -0
  155. package/dist/{restore-archive-9CGgeBzD.mjs → restore-archive-DR9MtO7J.mjs} +339 -9
  156. package/dist/{restore-archive-BMNXwWWD.js → restore-archive-DjJnCgap.js} +353 -5
  157. package/dist/tls/agent-https-names.d.ts +9 -13
  158. package/dist/{wal-maintenance-cRHR4rUY.js → wal-maintenance-CODGqhKY.js} +0 -0
  159. package/dist/{wal-maintenance-sIB32ONp.mjs → wal-maintenance-CfvgtQ7C.mjs} +0 -0
  160. 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-D9qT3jHr.js");
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
- const key = field["key"];
1123
- if (typeof key !== "string" || !("value" in field)) return field;
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 tombstones = new DeviceTombstoneStore({
10868
- backend: deviceRowBackendOf(settingsStoreApi),
10869
- logger: this.ctx.logger.child("tombstones")
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"));