@camstack/system 1.2.65 → 1.2.67
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/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/blocks-integration.d.ts +24 -0
- package/dist/builtins/core-blocks/core-blocks.addon.d.ts +14 -0
- package/dist/builtins/core-blocks/core-blocks.addon.js +99 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +99 -2
- package/dist/builtins/device-manager/device-manager.addon.js +3 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +3 -1
- 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 +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -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-DqPyKwVB.mjs → dist-CbS6uoSb.mjs} +2465 -2075
- package/dist/{dist-CIkGOAcz.js → dist-NRYjb8qK.js} +1891 -1489
- package/dist/index.js +28 -4
- package/dist/index.mjs +28 -4
- package/dist/kernel/cap-router-builder.d.ts +19 -0
- package/dist/kernel/capability-registry.d.ts +14 -1
- package/package.json +1 -1
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_fs = require("node:fs");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as addonPagesCapability, ft as errMsg, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as fs from "node:fs";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_fs = require("node:fs");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ft as errMsg, pt as BaseAddon, y as addonWidgetsCapability, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as fs from "node:fs";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
//#region src/builtins/alerts/prune-policy.ts
|
|
8
8
|
/**
|
|
9
9
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Et as createEvent, b as alertsCapability, ft as errMsg, n as AlertSchema, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
//#region src/builtins/alerts/prune-policy.ts
|
|
3
3
|
/**
|
|
4
4
|
* Ids older than `cutoffMs`, oldest first.
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
let node_fs$1 = require_chunk.__toESM(node_fs, 1);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as backupCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import Kt from "node:fs";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/console-logging/console-destination.ts
|
|
9
9
|
var LEVEL_RANK = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pt as BaseAddon, q as logDestinationCapability } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/console-logging/console-destination.ts
|
|
4
4
|
var LEVEL_RANK = {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DeclaredDevicePorts } from '@camstack/types';
|
|
2
|
+
/** Operator-visible name of the shared integration. Seeded once, at create. */
|
|
3
|
+
export declare const BLOCKS_INTEGRATION_NAME = "Blocks";
|
|
4
|
+
/**
|
|
5
|
+
* The declared-device ports minus the owner — `reconcileBlocksIntegration`
|
|
6
|
+
* pins that itself, because getting it wrong is the entire bug above.
|
|
7
|
+
*/
|
|
8
|
+
export type BlocksIntegrationPorts = Omit<DeclaredDevicePorts, 'addonId'>;
|
|
9
|
+
/**
|
|
10
|
+
* Reconcile the shared integration. Idempotent; safe on every boot.
|
|
11
|
+
*
|
|
12
|
+
* Returns its id, or `null` when this node does not own the declaration (it is
|
|
13
|
+
* hub-owned, like every declaration).
|
|
14
|
+
*
|
|
15
|
+
* **The trap, stated where it lives:** `devices: []` makes every row the index
|
|
16
|
+
* returns under this integration a withdrawal candidate. That is safe ONLY
|
|
17
|
+
* because `listOwnDevices` is scoped to `core-blocks` and a block's devices are
|
|
18
|
+
* owned by `core-block-<uuid>` — so the listing is empty. Two ways to destroy
|
|
19
|
+
* that: wire `listOwnDevices` without its owner filter (it would then answer
|
|
20
|
+
* with every device on the cluster, and the sweep would delete the blocks'), or
|
|
21
|
+
* make `core-blocks` declare a device of its own. Neither is worth the
|
|
22
|
+
* convenience; the spec test pins both.
|
|
23
|
+
*/
|
|
24
|
+
export declare function reconcileBlocksIntegration(ports: BlocksIntegrationPorts): Promise<string | null>;
|
|
@@ -12,6 +12,8 @@ export declare class CoreBlocksAddon extends BaseAddon {
|
|
|
12
12
|
private transpiler;
|
|
13
13
|
private typeDefs;
|
|
14
14
|
private supervisor;
|
|
15
|
+
/** The shared integration, or null when this node does not own it. */
|
|
16
|
+
private blocksIntegrationId;
|
|
15
17
|
protected onInitialize(): Promise<ProviderRegistration[]>;
|
|
16
18
|
protected onShutdown(): Promise<void>;
|
|
17
19
|
/**
|
|
@@ -22,6 +24,18 @@ export declare class CoreBlocksAddon extends BaseAddon {
|
|
|
22
24
|
* no cluster broker, which is the only door to `$process.*`.
|
|
23
25
|
*/
|
|
24
26
|
private buildSupervisor;
|
|
27
|
+
/**
|
|
28
|
+
* Own the integration blocks hang their devices from.
|
|
29
|
+
*
|
|
30
|
+
* A block cannot: every integration read is gated on the installed-addon set
|
|
31
|
+
* and `core-block-<uuid>` is never in it, so a block's get-or-create minted a
|
|
32
|
+
* fresh invisible row on every start. `core-blocks` IS installed, so it does
|
|
33
|
+
* this once here and a block names the result by id.
|
|
34
|
+
*
|
|
35
|
+
* Failure is a feature missing, not a boot failure — blocks that declare no
|
|
36
|
+
* devices are unaffected, and the next boot converges.
|
|
37
|
+
*/
|
|
38
|
+
private declareBlocksIntegration;
|
|
25
39
|
/**
|
|
26
40
|
* Reconcile now, after a write.
|
|
27
41
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_path = require("node:path");
|
|
6
6
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -667,6 +667,61 @@ var CoreBlockStore = class {
|
|
|
667
667
|
}
|
|
668
668
|
};
|
|
669
669
|
//#endregion
|
|
670
|
+
//#region src/builtins/core-blocks/blocks-integration.ts
|
|
671
|
+
/**
|
|
672
|
+
* The integration every block's devices hang from.
|
|
673
|
+
*
|
|
674
|
+
* ## Why it is not the block's own
|
|
675
|
+
*
|
|
676
|
+
* A core block CANNOT own an integration, and the failure was silent and
|
|
677
|
+
* accumulating. Every integration READ is gated on the installed-addon set
|
|
678
|
+
* (`addon-registry.service.ts` → `createFilteredRegistry`), and a block's addon
|
|
679
|
+
* id — `core-block-<uuid>` — is never in that set: a block is materialised and
|
|
680
|
+
* spawned, not installed. So `getIntegrationByAddonId` answered `null` forever
|
|
681
|
+
* while `createIntegration` succeeded, and every block start minted a fresh row
|
|
682
|
+
* that `listIntegrations` then hid and `integrations.delete` refused to remove.
|
|
683
|
+
* Measured on the live hub 2026-08-09: `int_0021` and `int_0022`, two starts of
|
|
684
|
+
* one block, invisible and undeletable through the API.
|
|
685
|
+
*
|
|
686
|
+
* `core-blocks` is an installed builtin, so it passes the filter. It reconciles
|
|
687
|
+
* ONE integration; a block names that integration by id
|
|
688
|
+
* (`DeclaredDevicesSpec.integrationId`) and mints nothing. Ownership of the
|
|
689
|
+
* DEVICE is untouched — that is `(addonId, stableId)`, and `listOwnDevices`
|
|
690
|
+
* stays addon-scoped, which is what keeps one block's withdrawal sweep away
|
|
691
|
+
* from another block's devices now that the integration no longer distinguishes
|
|
692
|
+
* them.
|
|
693
|
+
*
|
|
694
|
+
* The block-side read is
|
|
695
|
+
* `ctx.api.integrations.getByAddonId.query({ addonId: CORE_BLOCKS_ADDON_ID })`
|
|
696
|
+
* — legal, because `core-blocks` is installed. No new cap method is needed.
|
|
697
|
+
*/
|
|
698
|
+
/** Operator-visible name of the shared integration. Seeded once, at create. */
|
|
699
|
+
var BLOCKS_INTEGRATION_NAME = "Blocks";
|
|
700
|
+
/**
|
|
701
|
+
* Reconcile the shared integration. Idempotent; safe on every boot.
|
|
702
|
+
*
|
|
703
|
+
* Returns its id, or `null` when this node does not own the declaration (it is
|
|
704
|
+
* hub-owned, like every declaration).
|
|
705
|
+
*
|
|
706
|
+
* **The trap, stated where it lives:** `devices: []` makes every row the index
|
|
707
|
+
* returns under this integration a withdrawal candidate. That is safe ONLY
|
|
708
|
+
* because `listOwnDevices` is scoped to `core-blocks` and a block's devices are
|
|
709
|
+
* owned by `core-block-<uuid>` — so the listing is empty. Two ways to destroy
|
|
710
|
+
* that: wire `listOwnDevices` without its owner filter (it would then answer
|
|
711
|
+
* with every device on the cluster, and the sweep would delete the blocks'), or
|
|
712
|
+
* make `core-blocks` declare a device of its own. Neither is worth the
|
|
713
|
+
* convenience; the spec test pins both.
|
|
714
|
+
*/
|
|
715
|
+
async function reconcileBlocksIntegration(ports) {
|
|
716
|
+
return (await new require_dist.DeclaredDevices({
|
|
717
|
+
...ports,
|
|
718
|
+
addonId: require_dist.CORE_BLOCKS_ADDON_ID
|
|
719
|
+
}).reconcile({
|
|
720
|
+
integrationName: BLOCKS_INTEGRATION_NAME,
|
|
721
|
+
devices: []
|
|
722
|
+
})).integrationId;
|
|
723
|
+
}
|
|
724
|
+
//#endregion
|
|
670
725
|
//#region src/builtins/core-blocks/core-blocks.addon.ts
|
|
671
726
|
/**
|
|
672
727
|
* The `core-blocks` provider — CRUD over user-authored TypeScript, with the
|
|
@@ -710,6 +765,8 @@ var CoreBlocksAddon = class extends require_dist.BaseAddon {
|
|
|
710
765
|
transpiler = null;
|
|
711
766
|
typeDefs = null;
|
|
712
767
|
supervisor = null;
|
|
768
|
+
/** The shared integration, or null when this node does not own it. */
|
|
769
|
+
blocksIntegrationId = null;
|
|
713
770
|
async onInitialize() {
|
|
714
771
|
const settingsStore = this.ctx.api?.settingsStore;
|
|
715
772
|
if (!settingsStore) throw new Error("core-blocks: settings-store API not available — refusing to register the cap");
|
|
@@ -720,12 +777,14 @@ var CoreBlocksAddon = class extends require_dist.BaseAddon {
|
|
|
720
777
|
});
|
|
721
778
|
await this.store.load();
|
|
722
779
|
this.transpiler = await loadTranspiler(this.ctx.logger);
|
|
780
|
+
this.blocksIntegrationId = await this.declareBlocksIntegration();
|
|
723
781
|
this.supervisor = this.buildSupervisor();
|
|
724
782
|
this.supervisor?.start(CONVERGE_INTERVAL_MS);
|
|
725
783
|
this.ctx.logger.info("core-blocks ready", { meta: {
|
|
726
784
|
blocks: this.store.list().length,
|
|
727
785
|
compile: this.transpiler !== null,
|
|
728
|
-
supervising: this.supervisor !== null
|
|
786
|
+
supervising: this.supervisor !== null,
|
|
787
|
+
integrationId: this.blocksIntegrationId
|
|
729
788
|
} });
|
|
730
789
|
return [{
|
|
731
790
|
capability: require_dist.coreBlocksCapability,
|
|
@@ -782,6 +841,44 @@ var CoreBlocksAddon = class extends require_dist.BaseAddon {
|
|
|
782
841
|
});
|
|
783
842
|
}
|
|
784
843
|
/**
|
|
844
|
+
* Own the integration blocks hang their devices from.
|
|
845
|
+
*
|
|
846
|
+
* A block cannot: every integration read is gated on the installed-addon set
|
|
847
|
+
* and `core-block-<uuid>` is never in it, so a block's get-or-create minted a
|
|
848
|
+
* fresh invisible row on every start. `core-blocks` IS installed, so it does
|
|
849
|
+
* this once here and a block names the result by id.
|
|
850
|
+
*
|
|
851
|
+
* Failure is a feature missing, not a boot failure — blocks that declare no
|
|
852
|
+
* devices are unaffected, and the next boot converges.
|
|
853
|
+
*/
|
|
854
|
+
async declareBlocksIntegration() {
|
|
855
|
+
const api = this.ctx.api;
|
|
856
|
+
if (!api?.integrations || !api?.deviceManager) {
|
|
857
|
+
this.ctx.logger.warn("core-blocks: no integrations API — a block that declares a device will have nowhere to hang it");
|
|
858
|
+
return null;
|
|
859
|
+
}
|
|
860
|
+
try {
|
|
861
|
+
return await reconcileBlocksIntegration({
|
|
862
|
+
logger: this.ctx.logger.child("integration"),
|
|
863
|
+
devices: this.ctx.kernel.devices,
|
|
864
|
+
localNodeId: this.ctx.kernel.localNodeId,
|
|
865
|
+
getIntegration: async (addonId) => api.integrations.getByAddonId.query({ addonId }),
|
|
866
|
+
createIntegration: async (input) => api.integrations.create.mutate(input),
|
|
867
|
+
updateIntegration: async ({ id, info }) => {
|
|
868
|
+
await api.integrations.update.mutate({
|
|
869
|
+
id,
|
|
870
|
+
info,
|
|
871
|
+
skipRestart: true
|
|
872
|
+
});
|
|
873
|
+
},
|
|
874
|
+
listOwnDevices: async () => api.deviceManager.listAll.query({ addonId: require_dist.CORE_BLOCKS_ADDON_ID })
|
|
875
|
+
});
|
|
876
|
+
} catch (err) {
|
|
877
|
+
this.ctx.logger.warn("core-blocks: the shared integration could not be reconciled", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
878
|
+
return null;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
785
882
|
* Reconcile now, after a write.
|
|
786
883
|
*
|
|
787
884
|
* The timer would get there on its own, but an operator who presses Save and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { D as coreBlocksCapability, E as coreBlockIdFromAddonId, T as coreBlockAddonId, c as CoreBlockSchema, l as DeclaredDevices, o as CORE_BLOCKS_ADDON_ID, pt as BaseAddon, s as CORE_BLOCK_ADDON_PREFIX } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import * as path$1 from "node:path";
|
|
4
4
|
import * as fs from "node:fs/promises";
|
|
@@ -663,6 +663,61 @@ var CoreBlockStore = class {
|
|
|
663
663
|
}
|
|
664
664
|
};
|
|
665
665
|
//#endregion
|
|
666
|
+
//#region src/builtins/core-blocks/blocks-integration.ts
|
|
667
|
+
/**
|
|
668
|
+
* The integration every block's devices hang from.
|
|
669
|
+
*
|
|
670
|
+
* ## Why it is not the block's own
|
|
671
|
+
*
|
|
672
|
+
* A core block CANNOT own an integration, and the failure was silent and
|
|
673
|
+
* accumulating. Every integration READ is gated on the installed-addon set
|
|
674
|
+
* (`addon-registry.service.ts` → `createFilteredRegistry`), and a block's addon
|
|
675
|
+
* id — `core-block-<uuid>` — is never in that set: a block is materialised and
|
|
676
|
+
* spawned, not installed. So `getIntegrationByAddonId` answered `null` forever
|
|
677
|
+
* while `createIntegration` succeeded, and every block start minted a fresh row
|
|
678
|
+
* that `listIntegrations` then hid and `integrations.delete` refused to remove.
|
|
679
|
+
* Measured on the live hub 2026-08-09: `int_0021` and `int_0022`, two starts of
|
|
680
|
+
* one block, invisible and undeletable through the API.
|
|
681
|
+
*
|
|
682
|
+
* `core-blocks` is an installed builtin, so it passes the filter. It reconciles
|
|
683
|
+
* ONE integration; a block names that integration by id
|
|
684
|
+
* (`DeclaredDevicesSpec.integrationId`) and mints nothing. Ownership of the
|
|
685
|
+
* DEVICE is untouched — that is `(addonId, stableId)`, and `listOwnDevices`
|
|
686
|
+
* stays addon-scoped, which is what keeps one block's withdrawal sweep away
|
|
687
|
+
* from another block's devices now that the integration no longer distinguishes
|
|
688
|
+
* them.
|
|
689
|
+
*
|
|
690
|
+
* The block-side read is
|
|
691
|
+
* `ctx.api.integrations.getByAddonId.query({ addonId: CORE_BLOCKS_ADDON_ID })`
|
|
692
|
+
* — legal, because `core-blocks` is installed. No new cap method is needed.
|
|
693
|
+
*/
|
|
694
|
+
/** Operator-visible name of the shared integration. Seeded once, at create. */
|
|
695
|
+
var BLOCKS_INTEGRATION_NAME = "Blocks";
|
|
696
|
+
/**
|
|
697
|
+
* Reconcile the shared integration. Idempotent; safe on every boot.
|
|
698
|
+
*
|
|
699
|
+
* Returns its id, or `null` when this node does not own the declaration (it is
|
|
700
|
+
* hub-owned, like every declaration).
|
|
701
|
+
*
|
|
702
|
+
* **The trap, stated where it lives:** `devices: []` makes every row the index
|
|
703
|
+
* returns under this integration a withdrawal candidate. That is safe ONLY
|
|
704
|
+
* because `listOwnDevices` is scoped to `core-blocks` and a block's devices are
|
|
705
|
+
* owned by `core-block-<uuid>` — so the listing is empty. Two ways to destroy
|
|
706
|
+
* that: wire `listOwnDevices` without its owner filter (it would then answer
|
|
707
|
+
* with every device on the cluster, and the sweep would delete the blocks'), or
|
|
708
|
+
* make `core-blocks` declare a device of its own. Neither is worth the
|
|
709
|
+
* convenience; the spec test pins both.
|
|
710
|
+
*/
|
|
711
|
+
async function reconcileBlocksIntegration(ports) {
|
|
712
|
+
return (await new DeclaredDevices({
|
|
713
|
+
...ports,
|
|
714
|
+
addonId: CORE_BLOCKS_ADDON_ID
|
|
715
|
+
}).reconcile({
|
|
716
|
+
integrationName: BLOCKS_INTEGRATION_NAME,
|
|
717
|
+
devices: []
|
|
718
|
+
})).integrationId;
|
|
719
|
+
}
|
|
720
|
+
//#endregion
|
|
666
721
|
//#region src/builtins/core-blocks/core-blocks.addon.ts
|
|
667
722
|
/**
|
|
668
723
|
* The `core-blocks` provider — CRUD over user-authored TypeScript, with the
|
|
@@ -706,6 +761,8 @@ var CoreBlocksAddon = class extends BaseAddon {
|
|
|
706
761
|
transpiler = null;
|
|
707
762
|
typeDefs = null;
|
|
708
763
|
supervisor = null;
|
|
764
|
+
/** The shared integration, or null when this node does not own it. */
|
|
765
|
+
blocksIntegrationId = null;
|
|
709
766
|
async onInitialize() {
|
|
710
767
|
const settingsStore = this.ctx.api?.settingsStore;
|
|
711
768
|
if (!settingsStore) throw new Error("core-blocks: settings-store API not available — refusing to register the cap");
|
|
@@ -716,12 +773,14 @@ var CoreBlocksAddon = class extends BaseAddon {
|
|
|
716
773
|
});
|
|
717
774
|
await this.store.load();
|
|
718
775
|
this.transpiler = await loadTranspiler(this.ctx.logger);
|
|
776
|
+
this.blocksIntegrationId = await this.declareBlocksIntegration();
|
|
719
777
|
this.supervisor = this.buildSupervisor();
|
|
720
778
|
this.supervisor?.start(CONVERGE_INTERVAL_MS);
|
|
721
779
|
this.ctx.logger.info("core-blocks ready", { meta: {
|
|
722
780
|
blocks: this.store.list().length,
|
|
723
781
|
compile: this.transpiler !== null,
|
|
724
|
-
supervising: this.supervisor !== null
|
|
782
|
+
supervising: this.supervisor !== null,
|
|
783
|
+
integrationId: this.blocksIntegrationId
|
|
725
784
|
} });
|
|
726
785
|
return [{
|
|
727
786
|
capability: coreBlocksCapability,
|
|
@@ -778,6 +837,44 @@ var CoreBlocksAddon = class extends BaseAddon {
|
|
|
778
837
|
});
|
|
779
838
|
}
|
|
780
839
|
/**
|
|
840
|
+
* Own the integration blocks hang their devices from.
|
|
841
|
+
*
|
|
842
|
+
* A block cannot: every integration read is gated on the installed-addon set
|
|
843
|
+
* and `core-block-<uuid>` is never in it, so a block's get-or-create minted a
|
|
844
|
+
* fresh invisible row on every start. `core-blocks` IS installed, so it does
|
|
845
|
+
* this once here and a block names the result by id.
|
|
846
|
+
*
|
|
847
|
+
* Failure is a feature missing, not a boot failure — blocks that declare no
|
|
848
|
+
* devices are unaffected, and the next boot converges.
|
|
849
|
+
*/
|
|
850
|
+
async declareBlocksIntegration() {
|
|
851
|
+
const api = this.ctx.api;
|
|
852
|
+
if (!api?.integrations || !api?.deviceManager) {
|
|
853
|
+
this.ctx.logger.warn("core-blocks: no integrations API — a block that declares a device will have nowhere to hang it");
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
try {
|
|
857
|
+
return await reconcileBlocksIntegration({
|
|
858
|
+
logger: this.ctx.logger.child("integration"),
|
|
859
|
+
devices: this.ctx.kernel.devices,
|
|
860
|
+
localNodeId: this.ctx.kernel.localNodeId,
|
|
861
|
+
getIntegration: async (addonId) => api.integrations.getByAddonId.query({ addonId }),
|
|
862
|
+
createIntegration: async (input) => api.integrations.create.mutate(input),
|
|
863
|
+
updateIntegration: async ({ id, info }) => {
|
|
864
|
+
await api.integrations.update.mutate({
|
|
865
|
+
id,
|
|
866
|
+
info,
|
|
867
|
+
skipRestart: true
|
|
868
|
+
});
|
|
869
|
+
},
|
|
870
|
+
listOwnDevices: async () => api.deviceManager.listAll.query({ addonId: CORE_BLOCKS_ADDON_ID })
|
|
871
|
+
});
|
|
872
|
+
} catch (err) {
|
|
873
|
+
this.ctx.logger.warn("core-blocks: the shared integration could not be reconciled", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
781
878
|
* Reconcile now, after a write.
|
|
782
879
|
*
|
|
783
880
|
* The timer would get there on its own, but an operator who presses Save and
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let _camstack_types_node = require("@camstack/types/node");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
//#region src/builtins/device-manager/day-night-config-schema.ts
|
|
@@ -683,6 +683,8 @@ async function listPersistedByAddon(pctx, input) {
|
|
|
683
683
|
});
|
|
684
684
|
}
|
|
685
685
|
async function listAll(pctx, input) {
|
|
686
|
+
const ownerFilter = Reflect.get(input, "addonId");
|
|
687
|
+
if (ownerFilter !== void 0 && (typeof ownerFilter !== "string" || ownerFilter.length === 0)) throw new Error(`deviceManager.listAll: addonId must be a non-empty string or be omitted — got ${JSON.stringify(ownerFilter)}. An owner filter that is present but empty is never widened to every device. On an addon context the id is \`ctx.id\`; there is no \`ctx.addonId\`.`);
|
|
686
688
|
const { addonId } = input;
|
|
687
689
|
const slim = input.projection === "slim";
|
|
688
690
|
const camerasOnly = input.isCamera === true;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as deviceManagerCapability, F as enumerateItemArrayFields, I as enumerateSchemaFields, M as deviceStatusCapability, Rt as sleep, St as WELL_KNOWN_TAB_MAP, Z as normalizeUnit, _t as DeviceFeature, a as CAP_NAMES_WITH_STATUS, et as parseStreamParamsFormPatch, ft as errMsg, j as deviceStateCapability, jt as isDeviceConfigCap, p as STREAM_PROFILE_META, pt as BaseAddon, t as ALL_CAPABILITY_DEFINITIONS, u as DeviceStatusSchema, vt as DeviceRole, w as buildStreamParamsConfigSchema, yt as DeviceType, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { canonicalDeviceFingerprint } from "@camstack/types/node";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
//#region src/builtins/device-manager/day-night-config-schema.ts
|
|
@@ -678,6 +678,8 @@ async function listPersistedByAddon(pctx, input) {
|
|
|
678
678
|
});
|
|
679
679
|
}
|
|
680
680
|
async function listAll(pctx, input) {
|
|
681
|
+
const ownerFilter = Reflect.get(input, "addonId");
|
|
682
|
+
if (ownerFilter !== void 0 && (typeof ownerFilter !== "string" || ownerFilter.length === 0)) throw new Error(`deviceManager.listAll: addonId must be a non-empty string or be omitted — got ${JSON.stringify(ownerFilter)}. An owner filter that is present but empty is never widened to every device. On an addon context the id is \`ctx.id\`; there is no \`ctx.addonId\`.`);
|
|
681
683
|
const { addonId } = input;
|
|
682
684
|
const slim = input.projection === "slim";
|
|
683
685
|
const camerasOnly = input.isCamera === true;
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
8
8
|
/**
|
|
9
9
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as bareAddonId, Et as createEvent, H as isSameAddonId, N as doorbellCapability, ft as errMsg, pt as BaseAddon, yt as DeviceType, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
3
3
|
/**
|
|
4
4
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
9
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pt as BaseAddon, q as logDestinationCapability } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
4
4
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
4
4
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
5
5
|
var NO_DEVICES = "liveness:no-devices";
|
|
6
6
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Et as createEvent, ft as errMsg, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
3
3
|
var NO_DEVICES = "liveness:no-devices";
|
|
4
4
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
let crypto$1 = require("crypto");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Q as oauthIntegrationCapability, g as UserRecordSchema, lt as userManagementCapability, m as ScopedTokenSchema, pt as BaseAddon, r as ApiKeyRecordSchema, x as authProviderCapability } from "../../dist-CbS6uoSb.mjs";
|
|
3
3
|
import * as crypto$2 from "node:crypto";
|
|
4
4
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
5
5
|
import nodeCrypto from "crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
4
4
|
let node_os = require("node:os");
|
|
5
5
|
node_os = require_chunk.__toESM(node_os);
|
|
6
6
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { K as localNetworkCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
//#region src/builtins/local-network/local-network.addon.ts
|
|
4
4
|
/**
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
8
8
|
/**
|
|
9
9
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pt as BaseAddon, q as logDestinationCapability } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
3
3
|
/**
|
|
4
4
|
* Loki rejects a label name that is not a valid Prometheus label
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_util = require("node:util");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Et as createEvent, X as metricsProviderCapability, pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import { promisify } from "node:util";
|
|
4
4
|
import { execFile, execFileSync } from "node:child_process";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs);
|
|
9
9
|
let node_util = require("node:util");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Ot as emitReadiness, P as enumerateInferenceDevices, ft as errMsg, pt as BaseAddon, rt as scoreRuntimes, tt as platformProbeCapability, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import { execFile } from "node:child_process";
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
8
8
|
/**
|
|
9
9
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { pt as BaseAddon, zt as EventCategory } from "../../dist-CbS6uoSb.mjs";
|
|
2
2
|
//#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
|
|
3
3
|
/**
|
|
4
4
|
* Reconcile the durable `enabledProviders` set against authoritative
|
|
@@ -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-
|
|
6
|
+
const require_dist = require("../../dist-NRYjb8qK.js");
|
|
7
7
|
let node_child_process = require("node:child_process");
|
|
8
8
|
//#region src/builtins/snapshot/snapshot-coalescing.ts
|
|
9
9
|
/**
|