@camstack/system 1.2.275 → 1.2.276
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/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.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/camera-grid/grid-last-frame-store.d.ts +39 -0
- package/dist/builtins/camera-grid/index.js +67 -12
- package/dist/builtins/camera-grid/index.mjs +67 -12
- 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-aggregation.d.ts +0 -6
- package/dist/builtins/device-manager/device-bindings-store.d.ts +12 -2
- package/dist/builtins/device-manager/device-manager.addon.d.ts +4 -0
- package/dist/builtins/device-manager/device-manager.addon.js +177 -58
- package/dist/builtins/device-manager/device-manager.addon.mjs +174 -59
- package/dist/builtins/device-manager/device-meta-types.d.ts +36 -3
- package/dist/builtins/device-manager/device-source-activation.d.ts +70 -0
- 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/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-DWSJVcZe.mjs → dist-AHdiIdJH.mjs} +331 -12
- package/dist/{dist-CYXhwfDf.js → dist-D_OlSf31.js} +336 -11
- package/dist/index.d.ts +7 -0
- package/dist/index.js +103 -37
- package/dist/index.mjs +101 -39
- package/dist/kernel/capability-registry.d.ts +59 -9
- package/dist/kernel/index.d.ts +1 -0
- package/dist/{retired-settings-keys-BHGnCLW0.mjs → retired-settings-keys-Cp3oG_aH.mjs} +1 -1
- package/dist/{retired-settings-keys-DEFtUH8o.js → retired-settings-keys-LwFyTKun.js} +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -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-D_OlSf31.js");
|
|
4
4
|
const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
|
|
5
5
|
require("./builtins/alerts/index.js");
|
|
6
6
|
const require_formatter = require("./formatter-DqAKDlvN.js");
|
|
@@ -5892,8 +5892,23 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
5892
5892
|
singletonNodeOverrides = /* @__PURE__ */ new Map();
|
|
5893
5893
|
/** Optional reader for persisted per-node overrides: (cap, nodeId) → addonId. */
|
|
5894
5894
|
nodeConfigReader = null;
|
|
5895
|
-
/**
|
|
5896
|
-
|
|
5895
|
+
/**
|
|
5896
|
+
* Per-device SOURCE deactivations: deviceId → (capability → disabled addon ids).
|
|
5897
|
+
*
|
|
5898
|
+
* The in-memory PROJECTION of the persisted wrapper activation
|
|
5899
|
+
* (`deviceBindings[deviceId][capName].disabledSourceAddonIds`, written by
|
|
5900
|
+
* `setWrapperActive`), and never an authority of its own —
|
|
5901
|
+
* [D556](../../../../docs/decisions/adr-0556-a-per-device-source-switch-is-the-wrapper-activation-and-the-registry-holds-only-its-projection.md).
|
|
5902
|
+
* Nothing but `device-source-activation.ts` writes it: the operator's verb
|
|
5903
|
+
* is `deviceManager.setWrapperActive`, and a second writable surface here is
|
|
5904
|
+
* exactly the two-authorities defect D62 exists for.
|
|
5905
|
+
*
|
|
5906
|
+
* A DENY list, not an allow list, and that is the deliberate answer to what
|
|
5907
|
+
* "unset" means: a source nobody has ruled out is a source. An untouched
|
|
5908
|
+
* camera keeps every provider it has today, and a provider that registers
|
|
5909
|
+
* after the operator's last toggle needs no second write to be seen.
|
|
5910
|
+
*/
|
|
5911
|
+
deviceDisabledSources = /* @__PURE__ */ new Map();
|
|
5897
5912
|
/** autoActivate flags per (capability, addonId) — from addon manifests */
|
|
5898
5913
|
autoActivateFlags = /* @__PURE__ */ new Map();
|
|
5899
5914
|
/**
|
|
@@ -6789,54 +6804,73 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
6789
6804
|
for (const [addonId, provider] of state.providers) if (this.isActiveForSystem(capability, addonId)) return asProvider(provider);
|
|
6790
6805
|
return null;
|
|
6791
6806
|
}
|
|
6792
|
-
/**
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6807
|
+
/**
|
|
6808
|
+
* Mirror ONE device's persisted source deactivations for `capability` into
|
|
6809
|
+
* the projection (D556). The authority is the device-manager's
|
|
6810
|
+
* `deviceBindings` store; this is the read side of that write and the only
|
|
6811
|
+
* way the set changes.
|
|
6812
|
+
*
|
|
6813
|
+
* No check that `capability` is declared, and none that the addons are
|
|
6814
|
+
* registered: a persisted operator decision is a fact about the fleet, not a
|
|
6815
|
+
* reference to a live object, and replaying it at boot must not depend on
|
|
6816
|
+
* which addon happened to register first. An empty list drops the entry
|
|
6817
|
+
* (unset = every source).
|
|
6818
|
+
*/
|
|
6819
|
+
setDeviceDisabledSources(deviceId, capability, addonIds) {
|
|
6820
|
+
let deviceMap = this.deviceDisabledSources.get(deviceId);
|
|
6821
|
+
if (addonIds.length === 0) {
|
|
6822
|
+
if (!deviceMap) return;
|
|
6823
|
+
deviceMap.delete(capability);
|
|
6824
|
+
if (deviceMap.size === 0) this.deviceDisabledSources.delete(deviceId);
|
|
6825
|
+
this.logger.debug("Device source deactivations cleared", {
|
|
6826
|
+
tags: { deviceId: Number(deviceId) },
|
|
6827
|
+
meta: { capability }
|
|
6828
|
+
});
|
|
6796
6829
|
return;
|
|
6797
6830
|
}
|
|
6798
|
-
let deviceMap = this.deviceCollectionFilters.get(deviceId);
|
|
6799
6831
|
if (!deviceMap) {
|
|
6800
6832
|
deviceMap = /* @__PURE__ */ new Map();
|
|
6801
|
-
this.
|
|
6833
|
+
this.deviceDisabledSources.set(deviceId, deviceMap);
|
|
6802
6834
|
}
|
|
6803
|
-
deviceMap.set(capability,
|
|
6804
|
-
this.logger.
|
|
6835
|
+
deviceMap.set(capability, new Set(addonIds));
|
|
6836
|
+
this.logger.debug("Device source deactivations mirrored", {
|
|
6805
6837
|
tags: { deviceId: Number(deviceId) },
|
|
6806
6838
|
meta: {
|
|
6807
6839
|
capability,
|
|
6808
|
-
addonIds
|
|
6840
|
+
disabledAddonIds: [...addonIds]
|
|
6809
6841
|
}
|
|
6810
6842
|
});
|
|
6811
6843
|
}
|
|
6812
|
-
/**
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6844
|
+
/**
|
|
6845
|
+
* The addon ids the operator switched OFF as sources of this device for
|
|
6846
|
+
* `capability`. Empty means every source — never "none".
|
|
6847
|
+
*/
|
|
6848
|
+
getDeviceDisabledSources(deviceId, capability) {
|
|
6849
|
+
const disabled = this.deviceDisabledSources.get(deviceId)?.get(capability);
|
|
6850
|
+
return disabled === void 0 ? [] : [...disabled];
|
|
6851
|
+
}
|
|
6852
|
+
/** Is `addonId` switched off as a source of this device for `capability`? */
|
|
6853
|
+
isDeviceSourceDisabled(deviceId, capability, addonId) {
|
|
6854
|
+
return this.deviceDisabledSources.get(deviceId)?.get(capability)?.has(addonId) === true;
|
|
6822
6855
|
}
|
|
6823
6856
|
/**
|
|
6824
6857
|
* Resolve collection providers for a specific device.
|
|
6825
|
-
* Filters by activation (the manifest's autoActivate) and
|
|
6826
|
-
|
|
6827
|
-
|
|
6858
|
+
* Filters by activation (the manifest's autoActivate) and by the per-device
|
|
6859
|
+
* source deactivations the operator persisted (D556).
|
|
6860
|
+
*
|
|
6861
|
+
* `includeSwitchedOff` keeps the providers the operator switched off for this
|
|
6862
|
+
* device. It exists for ONE caller — the source LISTING path — because a
|
|
6863
|
+
* switched-off source must still produce a row to be switched back on from
|
|
6864
|
+
* (D554 decision 4, D556 as amended), and only its own provider can name it.
|
|
6865
|
+
* Every other path takes the default and sees the SERVING set: the sources
|
|
6866
|
+
* that may actually contribute.
|
|
6867
|
+
*/
|
|
6868
|
+
resolveCollectionForDevice(capability, deviceId, options) {
|
|
6828
6869
|
const state = this.capabilities.get(capability);
|
|
6829
6870
|
if (!state || state.definition.mode !== "collection") return [];
|
|
6830
|
-
|
|
6831
|
-
const
|
|
6832
|
-
|
|
6833
|
-
const filterAddonIds = deviceMap.get(capability);
|
|
6834
|
-
if (filterAddonIds) {
|
|
6835
|
-
const filterSet = new Set(filterAddonIds);
|
|
6836
|
-
entries = entries.filter(([addonId]) => filterSet.has(addonId));
|
|
6837
|
-
}
|
|
6838
|
-
}
|
|
6839
|
-
return entries.map(([, provider]) => asProvider(provider));
|
|
6871
|
+
const disabledForDevice = this.deviceDisabledSources.get(deviceId)?.get(capability);
|
|
6872
|
+
const keepSwitchedOff = options?.includeSwitchedOff === true;
|
|
6873
|
+
return [...state.providers.entries()].filter(([addonId]) => !state.disabledProviders.has(addonId)).filter(([addonId]) => this.isActiveForSystem(capability, addonId)).filter(([addonId]) => keepSwitchedOff || disabledForDevice?.has(addonId) !== true).map(([, provider]) => asProvider(provider));
|
|
6840
6874
|
}
|
|
6841
6875
|
/** Check if all dependencies for a capability are satisfied. */
|
|
6842
6876
|
areDependenciesMet(capabilityName) {
|
|
@@ -7000,6 +7034,35 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
7000
7034
|
function systemMountKindFor(def) {
|
|
7001
7035
|
return def.mode === "collection" ? "collection" : "singleton";
|
|
7002
7036
|
}
|
|
7037
|
+
/**
|
|
7038
|
+
* The mount kind ONE method resolves through — the cap's mount, except where
|
|
7039
|
+
* the method cannot be dispatched per device.
|
|
7040
|
+
*
|
|
7041
|
+
* Two ways a method leaves a per-device mount for the cap's SYSTEM provider:
|
|
7042
|
+
*
|
|
7043
|
+
* - `systemOnly: true` — declared via the `systemMethod()` factory. The
|
|
7044
|
+
* author said so; it wins everywhere, including on a `device-native` cap
|
|
7045
|
+
* (`snapshot.getSnapshotOverview`).
|
|
7046
|
+
* - a `device-scoped` cap's method whose input declares no top-level REQUIRED
|
|
7047
|
+
* numeric `deviceId`. The per-device dispatcher demands one on every call
|
|
7048
|
+
* (`requireDeviceScoped`), so such a method would answer BAD_REQUEST
|
|
7049
|
+
* "input must carry numeric deviceId" for every caller — unreachable. It
|
|
7050
|
+
* names no device, so there is no per-device provider to resolve: the cap's
|
|
7051
|
+
* hub-resident system/wrapper provider is the only honest destination, and
|
|
7052
|
+
* it is where that method already resolved before the mount was fixed.
|
|
7053
|
+
*
|
|
7054
|
+
* NOT applied to `device-native`, deliberately: there the native IS the device
|
|
7055
|
+
* and a deviceId-less method is a definition error the author must resolve
|
|
7056
|
+
* with `systemMethod()` — which is what `snapshot` does. This rule exists for
|
|
7057
|
+
* the mount kind that was DERIVED under caps that never opted in, where a
|
|
7058
|
+
* silent 400 would be a regression introduced by the derivation itself.
|
|
7059
|
+
*/
|
|
7060
|
+
function methodMountKindFor(def, mountKind, method) {
|
|
7061
|
+
if (method.schema.systemOnly === true) return systemMountKindFor(def);
|
|
7062
|
+
if (mountKind !== "device-scoped") return mountKind;
|
|
7063
|
+
if (require_dist.objectInputDeclaresRequiredDeviceId(method.schema.input)) return mountKind;
|
|
7064
|
+
return systemMountKindFor(def);
|
|
7065
|
+
}
|
|
7003
7066
|
function methodsFor(def) {
|
|
7004
7067
|
const effective = require_dist.expandCapMethods(def);
|
|
7005
7068
|
return Object.entries(effective).map(([name, schema]) => {
|
|
@@ -7126,12 +7189,11 @@ function requireLocal(capName, getLocal, services) {
|
|
|
7126
7189
|
function buildOneCapRouter(def, primitives, services) {
|
|
7127
7190
|
const capName = def.name;
|
|
7128
7191
|
const mount = require_dist.resolveCapMount(def);
|
|
7129
|
-
const systemMountKind = systemMountKindFor(def);
|
|
7130
7192
|
const nodeIdData = def.nodeIdMode === "data";
|
|
7131
7193
|
const procedures = {};
|
|
7132
7194
|
for (const method of methodsFor(def)) {
|
|
7133
7195
|
if (method.callerRequired && (method.kind === "subscription" || !method.isObject)) throw new Error(`Cap "${capName}" method "${method.name}": caller: 'required' is only supported on query/mutation methods with an object input schema`);
|
|
7134
|
-
const effectiveMountKind =
|
|
7196
|
+
const effectiveMountKind = methodMountKindFor(def, mount.kind, method);
|
|
7135
7197
|
const isCollection = effectiveMountKind === "collection";
|
|
7136
7198
|
const getLocal = (ctx, addonId) => services.getLocalProvider(capName, effectiveMountKind, ctx, addonId);
|
|
7137
7199
|
const base = primitives.procedures[require_dist.procedureAuthKey(method.auth)];
|
|
@@ -96177,12 +96239,14 @@ exports.isClusterSecretMismatchError = isClusterSecretMismatchError;
|
|
|
96177
96239
|
exports.isCollectionArrayMethod = require_dist.isCollectionArrayMethod;
|
|
96178
96240
|
exports.isInfraCapability = isInfraCapability;
|
|
96179
96241
|
exports.isModelDownloaded = require_event_loop_stall_monitor.isModelDownloaded;
|
|
96242
|
+
exports.isSourceDenied = require_builtins_device_manager_device_manager_addon.isSourceDenied;
|
|
96180
96243
|
exports.isSourceNewer = isSourceNewer;
|
|
96181
96244
|
exports.isolatedBuiltinPhase = isolatedBuiltinPhase;
|
|
96182
96245
|
exports.loadTlsCert = require_tls$1.loadTlsCert;
|
|
96183
96246
|
exports.localEndpointPath = require_manifest_system_deps.localEndpointPath;
|
|
96184
96247
|
exports.localProviderLink = require_manifest_system_deps.localProviderLink;
|
|
96185
96248
|
exports.mountNativeCapService = require_manifest_system_deps.mountNativeCapService;
|
|
96249
|
+
exports.nextDisabledSources = require_builtins_device_manager_device_manager_addon.nextDisabledSources;
|
|
96186
96250
|
exports.nextRssBudgetState = require_manifest_system_deps.nextRssBudgetState;
|
|
96187
96251
|
exports.parseCapAction = require_manifest_system_deps.parseCapAction;
|
|
96188
96252
|
exports.parseRangeHeader = require_event_loop_stall_monitor.parseRangeHeader;
|
|
@@ -96208,6 +96272,7 @@ exports.reissueTlsLeaf = require_tls$1.reissueTlsLeaf;
|
|
|
96208
96272
|
exports.resolveFilePath = require_event_loop_stall_monitor.resolveFilePath;
|
|
96209
96273
|
exports.resolveHwAccel = require_manifest_system_deps.resolveHwAccel;
|
|
96210
96274
|
exports.resolveNpmInvocation = require_manifest_system_deps.resolveNpmInvocation;
|
|
96275
|
+
exports.restoreDeviceSourceActivations = require_builtins_device_manager_device_manager_addon.restoreDeviceSourceActivations;
|
|
96211
96276
|
exports.runHubAddonBoot = runHubAddonBoot;
|
|
96212
96277
|
exports.runNpm = require_manifest_system_deps.runNpm;
|
|
96213
96278
|
exports.sampleSocketDirection = require_manifest_system_deps.sampleSocketDirection;
|
|
@@ -96220,6 +96285,7 @@ exports.selectReportedSpaces = require_manifest_system_deps.selectReportedSpaces
|
|
|
96220
96285
|
exports.serializeTypedArrays = require_manifest_system_deps.serializeTypedArrays;
|
|
96221
96286
|
exports.setHubConnected = require_manifest_system_deps.setHubConnected;
|
|
96222
96287
|
exports.setNodeEventInterest = require_manifest_system_deps.setNodeEventInterest;
|
|
96288
|
+
exports.setWrapperActive = require_builtins_device_manager_device_manager_addon.setWrapperActive;
|
|
96223
96289
|
exports.shouldReclaim = require_manifest_system_deps.shouldReclaim;
|
|
96224
96290
|
exports.socketDirectionBytes = require_manifest_system_deps.socketDirectionBytes;
|
|
96225
96291
|
exports.socketDirectionMessages = require_manifest_system_deps.socketDirectionMessages;
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { An as
|
|
2
|
+
import { An as parseJsonUnknown, F as addonSettingsCapability, Fn as EventCategory$1, Gt as scopesAllowDeviceCap, Ht as resolveMethodAuth, It as procedureAuthKey, Mn as resolveCapMount, Mt as objectInputDeclaresAddonId, Nn as scopeKey, Nt as objectInputDeclaresRequiredDeviceId, S as RUNTIME_DEFAULTS, Sn as emitDownForOwnedCaps, Tt as looseSchema, Wt as scopesAllowAddon, _t as isVoidInput, bn as asString$1, bt as lifecycleJobSchema, dn as DEVICE_STATUS_METHOD, dt as isArrayOutputSchema, ft as isCollectionArrayMethod, g as LOG_LEVEL_RANK, gn as ReadinessTimeoutError, hn as ReadinessRegistry, jn as readinessKey, kn as parseJsonObject, ln as DATAPLANE_SECRET_HEADER$1, mt as isObjectInput, on as errMsg$1, st as extractNestedAddonId, t as ALL_CAPABILITY_DEFINITIONS, un as DEVICE_SETTINGS_CONTRIBUTION_METHODS, vn as asJsonObject$1, vt as kebabToCamel, wn as expandCapMethods, wt as logLevelAtMost, xn as createEvent, y as METHOD_ACCESS_MAP, yn as asNumber } from "./dist-AHdiIdJH.mjs";
|
|
3
3
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
4
4
|
import "./builtins/alerts/index.mjs";
|
|
5
5
|
import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
|
|
6
6
|
import { ConsoleDestination, ConsoleLoggingAddon } from "./builtins/console-logging/index.mjs";
|
|
7
7
|
import { CoreBlocksAddon } from "./builtins/core-blocks/core-blocks.addon.mjs";
|
|
8
8
|
import "./builtins/core-blocks/index.mjs";
|
|
9
|
-
import { DeviceManagerAddon } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
9
|
+
import { DeviceManagerAddon, i as setWrapperActive, n as nextDisabledSources, r as restoreDeviceSourceActivations, t as isSourceDenied } from "./builtins/device-manager/device-manager.addon.mjs";
|
|
10
10
|
import "./builtins/device-manager/index.mjs";
|
|
11
11
|
import { HubForwarderAddon, HubForwarderDestination } from "./builtins/hub-forwarder/index.mjs";
|
|
12
12
|
import { LivenessMonitorAddon } from "./builtins/liveness-monitor/liveness-monitor.addon.mjs";
|
|
@@ -5885,8 +5885,23 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
5885
5885
|
singletonNodeOverrides = /* @__PURE__ */ new Map();
|
|
5886
5886
|
/** Optional reader for persisted per-node overrides: (cap, nodeId) → addonId. */
|
|
5887
5887
|
nodeConfigReader = null;
|
|
5888
|
-
/**
|
|
5889
|
-
|
|
5888
|
+
/**
|
|
5889
|
+
* Per-device SOURCE deactivations: deviceId → (capability → disabled addon ids).
|
|
5890
|
+
*
|
|
5891
|
+
* The in-memory PROJECTION of the persisted wrapper activation
|
|
5892
|
+
* (`deviceBindings[deviceId][capName].disabledSourceAddonIds`, written by
|
|
5893
|
+
* `setWrapperActive`), and never an authority of its own —
|
|
5894
|
+
* [D556](../../../../docs/decisions/adr-0556-a-per-device-source-switch-is-the-wrapper-activation-and-the-registry-holds-only-its-projection.md).
|
|
5895
|
+
* Nothing but `device-source-activation.ts` writes it: the operator's verb
|
|
5896
|
+
* is `deviceManager.setWrapperActive`, and a second writable surface here is
|
|
5897
|
+
* exactly the two-authorities defect D62 exists for.
|
|
5898
|
+
*
|
|
5899
|
+
* A DENY list, not an allow list, and that is the deliberate answer to what
|
|
5900
|
+
* "unset" means: a source nobody has ruled out is a source. An untouched
|
|
5901
|
+
* camera keeps every provider it has today, and a provider that registers
|
|
5902
|
+
* after the operator's last toggle needs no second write to be seen.
|
|
5903
|
+
*/
|
|
5904
|
+
deviceDisabledSources = /* @__PURE__ */ new Map();
|
|
5890
5905
|
/** autoActivate flags per (capability, addonId) — from addon manifests */
|
|
5891
5906
|
autoActivateFlags = /* @__PURE__ */ new Map();
|
|
5892
5907
|
/**
|
|
@@ -6782,54 +6797,73 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
6782
6797
|
for (const [addonId, provider] of state.providers) if (this.isActiveForSystem(capability, addonId)) return asProvider(provider);
|
|
6783
6798
|
return null;
|
|
6784
6799
|
}
|
|
6785
|
-
/**
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6800
|
+
/**
|
|
6801
|
+
* Mirror ONE device's persisted source deactivations for `capability` into
|
|
6802
|
+
* the projection (D556). The authority is the device-manager's
|
|
6803
|
+
* `deviceBindings` store; this is the read side of that write and the only
|
|
6804
|
+
* way the set changes.
|
|
6805
|
+
*
|
|
6806
|
+
* No check that `capability` is declared, and none that the addons are
|
|
6807
|
+
* registered: a persisted operator decision is a fact about the fleet, not a
|
|
6808
|
+
* reference to a live object, and replaying it at boot must not depend on
|
|
6809
|
+
* which addon happened to register first. An empty list drops the entry
|
|
6810
|
+
* (unset = every source).
|
|
6811
|
+
*/
|
|
6812
|
+
setDeviceDisabledSources(deviceId, capability, addonIds) {
|
|
6813
|
+
let deviceMap = this.deviceDisabledSources.get(deviceId);
|
|
6814
|
+
if (addonIds.length === 0) {
|
|
6815
|
+
if (!deviceMap) return;
|
|
6816
|
+
deviceMap.delete(capability);
|
|
6817
|
+
if (deviceMap.size === 0) this.deviceDisabledSources.delete(deviceId);
|
|
6818
|
+
this.logger.debug("Device source deactivations cleared", {
|
|
6819
|
+
tags: { deviceId: Number(deviceId) },
|
|
6820
|
+
meta: { capability }
|
|
6821
|
+
});
|
|
6789
6822
|
return;
|
|
6790
6823
|
}
|
|
6791
|
-
let deviceMap = this.deviceCollectionFilters.get(deviceId);
|
|
6792
6824
|
if (!deviceMap) {
|
|
6793
6825
|
deviceMap = /* @__PURE__ */ new Map();
|
|
6794
|
-
this.
|
|
6826
|
+
this.deviceDisabledSources.set(deviceId, deviceMap);
|
|
6795
6827
|
}
|
|
6796
|
-
deviceMap.set(capability,
|
|
6797
|
-
this.logger.
|
|
6828
|
+
deviceMap.set(capability, new Set(addonIds));
|
|
6829
|
+
this.logger.debug("Device source deactivations mirrored", {
|
|
6798
6830
|
tags: { deviceId: Number(deviceId) },
|
|
6799
6831
|
meta: {
|
|
6800
6832
|
capability,
|
|
6801
|
-
addonIds
|
|
6833
|
+
disabledAddonIds: [...addonIds]
|
|
6802
6834
|
}
|
|
6803
6835
|
});
|
|
6804
6836
|
}
|
|
6805
|
-
/**
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6837
|
+
/**
|
|
6838
|
+
* The addon ids the operator switched OFF as sources of this device for
|
|
6839
|
+
* `capability`. Empty means every source — never "none".
|
|
6840
|
+
*/
|
|
6841
|
+
getDeviceDisabledSources(deviceId, capability) {
|
|
6842
|
+
const disabled = this.deviceDisabledSources.get(deviceId)?.get(capability);
|
|
6843
|
+
return disabled === void 0 ? [] : [...disabled];
|
|
6844
|
+
}
|
|
6845
|
+
/** Is `addonId` switched off as a source of this device for `capability`? */
|
|
6846
|
+
isDeviceSourceDisabled(deviceId, capability, addonId) {
|
|
6847
|
+
return this.deviceDisabledSources.get(deviceId)?.get(capability)?.has(addonId) === true;
|
|
6815
6848
|
}
|
|
6816
6849
|
/**
|
|
6817
6850
|
* Resolve collection providers for a specific device.
|
|
6818
|
-
* Filters by activation (the manifest's autoActivate) and
|
|
6819
|
-
|
|
6820
|
-
|
|
6851
|
+
* Filters by activation (the manifest's autoActivate) and by the per-device
|
|
6852
|
+
* source deactivations the operator persisted (D556).
|
|
6853
|
+
*
|
|
6854
|
+
* `includeSwitchedOff` keeps the providers the operator switched off for this
|
|
6855
|
+
* device. It exists for ONE caller — the source LISTING path — because a
|
|
6856
|
+
* switched-off source must still produce a row to be switched back on from
|
|
6857
|
+
* (D554 decision 4, D556 as amended), and only its own provider can name it.
|
|
6858
|
+
* Every other path takes the default and sees the SERVING set: the sources
|
|
6859
|
+
* that may actually contribute.
|
|
6860
|
+
*/
|
|
6861
|
+
resolveCollectionForDevice(capability, deviceId, options) {
|
|
6821
6862
|
const state = this.capabilities.get(capability);
|
|
6822
6863
|
if (!state || state.definition.mode !== "collection") return [];
|
|
6823
|
-
|
|
6824
|
-
const
|
|
6825
|
-
|
|
6826
|
-
const filterAddonIds = deviceMap.get(capability);
|
|
6827
|
-
if (filterAddonIds) {
|
|
6828
|
-
const filterSet = new Set(filterAddonIds);
|
|
6829
|
-
entries = entries.filter(([addonId]) => filterSet.has(addonId));
|
|
6830
|
-
}
|
|
6831
|
-
}
|
|
6832
|
-
return entries.map(([, provider]) => asProvider(provider));
|
|
6864
|
+
const disabledForDevice = this.deviceDisabledSources.get(deviceId)?.get(capability);
|
|
6865
|
+
const keepSwitchedOff = options?.includeSwitchedOff === true;
|
|
6866
|
+
return [...state.providers.entries()].filter(([addonId]) => !state.disabledProviders.has(addonId)).filter(([addonId]) => this.isActiveForSystem(capability, addonId)).filter(([addonId]) => keepSwitchedOff || disabledForDevice?.has(addonId) !== true).map(([, provider]) => asProvider(provider));
|
|
6833
6867
|
}
|
|
6834
6868
|
/** Check if all dependencies for a capability are satisfied. */
|
|
6835
6869
|
areDependenciesMet(capabilityName) {
|
|
@@ -6993,6 +7027,35 @@ var CapabilityRegistry = class CapabilityRegistry {
|
|
|
6993
7027
|
function systemMountKindFor(def) {
|
|
6994
7028
|
return def.mode === "collection" ? "collection" : "singleton";
|
|
6995
7029
|
}
|
|
7030
|
+
/**
|
|
7031
|
+
* The mount kind ONE method resolves through — the cap's mount, except where
|
|
7032
|
+
* the method cannot be dispatched per device.
|
|
7033
|
+
*
|
|
7034
|
+
* Two ways a method leaves a per-device mount for the cap's SYSTEM provider:
|
|
7035
|
+
*
|
|
7036
|
+
* - `systemOnly: true` — declared via the `systemMethod()` factory. The
|
|
7037
|
+
* author said so; it wins everywhere, including on a `device-native` cap
|
|
7038
|
+
* (`snapshot.getSnapshotOverview`).
|
|
7039
|
+
* - a `device-scoped` cap's method whose input declares no top-level REQUIRED
|
|
7040
|
+
* numeric `deviceId`. The per-device dispatcher demands one on every call
|
|
7041
|
+
* (`requireDeviceScoped`), so such a method would answer BAD_REQUEST
|
|
7042
|
+
* "input must carry numeric deviceId" for every caller — unreachable. It
|
|
7043
|
+
* names no device, so there is no per-device provider to resolve: the cap's
|
|
7044
|
+
* hub-resident system/wrapper provider is the only honest destination, and
|
|
7045
|
+
* it is where that method already resolved before the mount was fixed.
|
|
7046
|
+
*
|
|
7047
|
+
* NOT applied to `device-native`, deliberately: there the native IS the device
|
|
7048
|
+
* and a deviceId-less method is a definition error the author must resolve
|
|
7049
|
+
* with `systemMethod()` — which is what `snapshot` does. This rule exists for
|
|
7050
|
+
* the mount kind that was DERIVED under caps that never opted in, where a
|
|
7051
|
+
* silent 400 would be a regression introduced by the derivation itself.
|
|
7052
|
+
*/
|
|
7053
|
+
function methodMountKindFor(def, mountKind, method) {
|
|
7054
|
+
if (method.schema.systemOnly === true) return systemMountKindFor(def);
|
|
7055
|
+
if (mountKind !== "device-scoped") return mountKind;
|
|
7056
|
+
if (objectInputDeclaresRequiredDeviceId(method.schema.input)) return mountKind;
|
|
7057
|
+
return systemMountKindFor(def);
|
|
7058
|
+
}
|
|
6996
7059
|
function methodsFor(def) {
|
|
6997
7060
|
const effective = expandCapMethods(def);
|
|
6998
7061
|
return Object.entries(effective).map(([name, schema]) => {
|
|
@@ -7119,12 +7182,11 @@ function requireLocal(capName, getLocal, services) {
|
|
|
7119
7182
|
function buildOneCapRouter(def, primitives, services) {
|
|
7120
7183
|
const capName = def.name;
|
|
7121
7184
|
const mount = resolveCapMount(def);
|
|
7122
|
-
const systemMountKind = systemMountKindFor(def);
|
|
7123
7185
|
const nodeIdData = def.nodeIdMode === "data";
|
|
7124
7186
|
const procedures = {};
|
|
7125
7187
|
for (const method of methodsFor(def)) {
|
|
7126
7188
|
if (method.callerRequired && (method.kind === "subscription" || !method.isObject)) throw new Error(`Cap "${capName}" method "${method.name}": caller: 'required' is only supported on query/mutation methods with an object input schema`);
|
|
7127
|
-
const effectiveMountKind =
|
|
7189
|
+
const effectiveMountKind = methodMountKindFor(def, mount.kind, method);
|
|
7128
7190
|
const isCollection = effectiveMountKind === "collection";
|
|
7129
7191
|
const getLocal = (ctx, addonId) => services.getLocalProvider(capName, effectiveMountKind, ctx, addonId);
|
|
7130
7192
|
const base = primitives.procedures[procedureAuthKey(method.auth)];
|
|
@@ -95817,4 +95879,4 @@ var LifecycleJobEngine = class {
|
|
|
95817
95879
|
}
|
|
95818
95880
|
};
|
|
95819
95881
|
//#endregion
|
|
95820
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, nextRssBudgetState, parseCapAction, parseRangeHeader, parseRssBudgetMb, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readHeapSpaces, readLanHttpState, readMoleculerFanoutMode, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, setHubConnected, setNodeEventInterest, shouldReclaim, socketDirectionBytes, socketDirectionMessages, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
95882
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, ARRAY_BUFFER_CENSUS_COOLDOWN_MS, ARRAY_BUFFER_CENSUS_SUSTAIN_MS, ARRAY_BUFFER_CENSUS_THRESHOLD_MB, ARRAY_BUFFER_RELEASE_MIN_DROP_RATIO, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, CAP_ACTION_OVERFLOW_LABEL, CAP_ACTION_UNLABELLED, CA_COMMON_NAME, CA_VALIDITY_DAYS, CLUSTER_SECRET_MISMATCH_TYPE, CLUSTER_SECRET_REJECTED_EXIT_CODE, CORE_CAP_SERVICE_NAME, CapRouteError, CapRouteResolver, CapUsageRegistry, CapabilityHandle, CapabilityRegistry, CapabilityUnavailableError, ConfigManager, ConfigStore, ConsoleDestination, ConsoleLoggingAddon, CoreBlocksAddon, CustomActionRegistry, DECISIVE_HEAP_SPACES, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, EMPTY_CAP_ACTION_READING, EMPTY_SOCKET_DIRECTION, EMPTY_SOCKET_PLANE_BASELINE, EVENT_PLANE_TOP_N, EVENT_TOPIC_PREFIX, EngineManagerResolver, EventBus, FeatureManager, FilesystemStorageAddon, FilesystemStorageProvider, FrameDecoder, FsStorageBackend, HEALTH_MONITOR_GRACE_PERIOD_MS, HEALTH_MONITOR_RETRY_INTERVALS_MS, HEALTH_MONITOR_TICK_MS, HEAP_RECLAIM_MIN_INTERVAL_MS, HEAP_RECLAIM_STEADY_STATE_INTERVAL_MS, HEAP_RECLAIM_TRIGGER_MB, HEAP_SPACE_REPORT_MIN_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HUB_MAIN_HEAP_WATCH_LABEL, HUB_MAIN_RSS_BUDGET_MB, HUB_RSS_BUDGET_ENV, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LokiDestination, LokiLoggingAddon, MAX_CAP_ACTIONS_PER_PEER, MAX_LEAF_VALIDITY_DAYS, MESH_QUEUE_TOP_N, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, OUTBOUND_QUEUE_COOLDOWN_MS, OUTBOUND_QUEUE_SUSTAIN_MS, OUTBOUND_QUEUE_THRESHOLD_BYTES, PARENT_ROUTED_PROVIDER_ADDON_ID, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RSS_BUDGET_REANNOUNCE_MIN_MS, RSS_BUDGET_RELEASE_RATIO, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNNER_RSS_BUDGET_ENV, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, SOCKET_PLANE_TOP_N, SOCKET_QUEUE_TOP_N, STALL_REPORT_MS, STALL_TICK_MS, ScopedLogger, ScopedTokenManager, SocketChannel, SqliteSettingsAddon, SqliteSettingsBackend, StagingArea, StorageLocationManager, StorageManager, StorageOrchestratorAddon, StorageOrchestratorService, SystemConfigAddon, SystemEventBus, TRADITIONAL_NATIVE_PACKAGES, ToastService, UDS_NO_ROUTE_PREFIX, UdsLocalTransportClient, UdsLocalTransportServer, UserManager, WinstonDestination, WinstonLoggingAddon, ZERO_LOOP_DELAY, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, attributeStall, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildNpmChildEnv, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionLabel, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createArrayBufferCensusGate, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCapActionCensus, createCoreCapService, createDeferredHeapWatchSink, createDoorSettingsView, createEventPlaneMeter, createEventPlaneReader, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createInspectorArrayBufferCensus, createKernelHwAccel, createLocalTransport, createLoopDelayMeter, createMeshQueueReader, createOutboundQueueGate, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createSocketDirectionCounters, createSocketPlaneMeter, createSocketPlaneReader, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, describeRss, detectWorkspacePackagesDir, deviceCapResolverLink, diffCapActionCensus, diffEventPlane, diffSocketPlane, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, emitHeapDiagnosticReport, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatArrayBufferCensus, formatEventPlane, formatHeapSpaces, formatLogLine, formatMeshQueue, formatOutboundQueueVerdict, formatSocketPlane, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, heapSpaceField, hubMainRssBudget, installManifestNativeDeps, installManifestPythonDeps, installManifestSystemDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayBufferCensusReport, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceDenied, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, nextDisabledSources, nextRssBudgetState, parseCapAction, parseRangeHeader, parseRssBudgetMb, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readHeapSpaces, readLanHttpState, readMoleculerFanoutMode, readPendingRestart, readSocketQueues, readTlsAccessStatus, readTlsMode, readinessKey, reclaimIntervalMs, recordSocketFrame, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, restoreDeviceSourceActivations, runHubAddonBoot, runNpm, sampleSocketDirection, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, selectReportedSpaces, serializeTypedArrays, setHubConnected, setNodeEventInterest, setWrapperActive, shouldReclaim, socketDirectionBytes, socketDirectionMessages, startEventLoopStallMonitor, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
@@ -30,6 +30,17 @@ export type CollectionConfigReader = (capability: string) => readonly string[] |
|
|
|
30
30
|
* cannot present it. See docs/decisions/adr-0188-an-unregister-carries-proof-of-ownership.md.
|
|
31
31
|
*/
|
|
32
32
|
export type ProviderOwnerToken = string;
|
|
33
|
+
/**
|
|
34
|
+
* How much of a device's COLLECTION a caller is asking for.
|
|
35
|
+
*
|
|
36
|
+
* The default — and every caller that intends to USE the providers — is the
|
|
37
|
+
* serving set: the sources that may contribute. The source LISTING path asks
|
|
38
|
+
* for the whole set instead, because a source the operator switched off must
|
|
39
|
+
* still produce a row to be switched back on from (D556 as amended).
|
|
40
|
+
*/
|
|
41
|
+
export interface DeviceCollectionResolution {
|
|
42
|
+
readonly includeSwitchedOff: boolean;
|
|
43
|
+
}
|
|
33
44
|
export declare class CapabilityRegistry {
|
|
34
45
|
private readonly capabilities;
|
|
35
46
|
private readonly logger;
|
|
@@ -59,8 +70,23 @@ export declare class CapabilityRegistry {
|
|
|
59
70
|
private readonly singletonNodeOverrides;
|
|
60
71
|
/** Optional reader for persisted per-node overrides: (cap, nodeId) → addonId. */
|
|
61
72
|
private nodeConfigReader;
|
|
62
|
-
/**
|
|
63
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Per-device SOURCE deactivations: deviceId → (capability → disabled addon ids).
|
|
75
|
+
*
|
|
76
|
+
* The in-memory PROJECTION of the persisted wrapper activation
|
|
77
|
+
* (`deviceBindings[deviceId][capName].disabledSourceAddonIds`, written by
|
|
78
|
+
* `setWrapperActive`), and never an authority of its own —
|
|
79
|
+
* [D556](../../../../docs/decisions/adr-0556-a-per-device-source-switch-is-the-wrapper-activation-and-the-registry-holds-only-its-projection.md).
|
|
80
|
+
* Nothing but `device-source-activation.ts` writes it: the operator's verb
|
|
81
|
+
* is `deviceManager.setWrapperActive`, and a second writable surface here is
|
|
82
|
+
* exactly the two-authorities defect D62 exists for.
|
|
83
|
+
*
|
|
84
|
+
* A DENY list, not an allow list, and that is the deliberate answer to what
|
|
85
|
+
* "unset" means: a source nobody has ruled out is a source. An untouched
|
|
86
|
+
* camera keeps every provider it has today, and a provider that registers
|
|
87
|
+
* after the operator's last toggle needs no second write to be seen.
|
|
88
|
+
*/
|
|
89
|
+
private readonly deviceDisabledSources;
|
|
64
90
|
/** autoActivate flags per (capability, addonId) — from addon manifests */
|
|
65
91
|
private readonly autoActivateFlags;
|
|
66
92
|
/**
|
|
@@ -465,15 +491,39 @@ export declare class CapabilityRegistry {
|
|
|
465
491
|
* singleton override — the in-memory provider pin, not a persisted flag.
|
|
466
492
|
*/
|
|
467
493
|
resolveForDevice<T = unknown>(capability: string, deviceId: string): T | null;
|
|
468
|
-
/** Set a per-device collection filter. */
|
|
469
|
-
setDeviceCollectionFilter(deviceId: string, capability: string, addonIds: string[]): void;
|
|
470
|
-
/** Clear a per-device collection filter. */
|
|
471
|
-
clearDeviceCollectionFilter(deviceId: string, capability: string): void;
|
|
472
494
|
/**
|
|
473
|
-
*
|
|
474
|
-
*
|
|
495
|
+
* Mirror ONE device's persisted source deactivations for `capability` into
|
|
496
|
+
* the projection (D556). The authority is the device-manager's
|
|
497
|
+
* `deviceBindings` store; this is the read side of that write and the only
|
|
498
|
+
* way the set changes.
|
|
499
|
+
*
|
|
500
|
+
* No check that `capability` is declared, and none that the addons are
|
|
501
|
+
* registered: a persisted operator decision is a fact about the fleet, not a
|
|
502
|
+
* reference to a live object, and replaying it at boot must not depend on
|
|
503
|
+
* which addon happened to register first. An empty list drops the entry
|
|
504
|
+
* (unset = every source).
|
|
505
|
+
*/
|
|
506
|
+
setDeviceDisabledSources(deviceId: string, capability: string, addonIds: readonly string[]): void;
|
|
507
|
+
/**
|
|
508
|
+
* The addon ids the operator switched OFF as sources of this device for
|
|
509
|
+
* `capability`. Empty means every source — never "none".
|
|
475
510
|
*/
|
|
476
|
-
|
|
511
|
+
getDeviceDisabledSources(deviceId: string, capability: string): readonly string[];
|
|
512
|
+
/** Is `addonId` switched off as a source of this device for `capability`? */
|
|
513
|
+
isDeviceSourceDisabled(deviceId: string, capability: string, addonId: string): boolean;
|
|
514
|
+
/**
|
|
515
|
+
* Resolve collection providers for a specific device.
|
|
516
|
+
* Filters by activation (the manifest's autoActivate) and by the per-device
|
|
517
|
+
* source deactivations the operator persisted (D556).
|
|
518
|
+
*
|
|
519
|
+
* `includeSwitchedOff` keeps the providers the operator switched off for this
|
|
520
|
+
* device. It exists for ONE caller — the source LISTING path — because a
|
|
521
|
+
* switched-off source must still produce a row to be switched back on from
|
|
522
|
+
* (D554 decision 4, D556 as amended), and only its own provider can name it.
|
|
523
|
+
* Every other path takes the default and sees the SERVING set: the sources
|
|
524
|
+
* that may actually contribute.
|
|
525
|
+
*/
|
|
526
|
+
resolveCollectionForDevice<T = unknown>(capability: string, deviceId: string, options?: DeviceCollectionResolution): readonly T[];
|
|
477
527
|
/** Check if all dependencies for a capability are satisfied. */
|
|
478
528
|
areDependenciesMet(capabilityName: string): boolean;
|
|
479
529
|
/** Get topologically sorted boot order based on dependsOn. */
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { RESTART_MARKER_FILE, clearPendingRestart, getRestartMarkerPath, readPen
|
|
|
13
13
|
export type { PendingRestartMarker, RestartKind, ScheduleSelfRestartOptions, } from './restart-coordinator.js';
|
|
14
14
|
export { CapabilityHandle, CapabilityUnavailableError } from './capability-handle.js';
|
|
15
15
|
export { CapabilityRegistry } from './capability-registry.js';
|
|
16
|
+
export type { DeviceCollectionResolution } from './capability-registry.js';
|
|
16
17
|
export { buildCapRouters, builderMountedCapNames } from './cap-router-builder.js';
|
|
17
18
|
export type { CapRouterPrimitives, CapRouterServices, CapProviderGetter, RemoteProxyFactory, ProcedureBuilder, ProcedureResolverArgs, } from './cap-router-builder.js';
|
|
18
19
|
export { describeProviderKindDrift } from './provider-kind-drift.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/system",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.276",
|
|
4
4
|
"description": "Core addon for CamStack — builtins, pipeline, process management, auth, logging, events",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"camstack",
|
|
@@ -392,7 +392,6 @@
|
|
|
392
392
|
"@camstack/sdk": "*",
|
|
393
393
|
"@camstack/types": "*",
|
|
394
394
|
"@msgpack/msgpack": "^3.1.3",
|
|
395
|
-
"@peculiar/x509": "^1.14.3",
|
|
396
395
|
"@trpc/client": "^11.16.0",
|
|
397
396
|
"@trpc/server": "^11.16.0",
|
|
398
397
|
"bcryptjs": "^3.0.3",
|
|
@@ -416,6 +415,7 @@
|
|
|
416
415
|
},
|
|
417
416
|
"devDependencies": {
|
|
418
417
|
"@camstack/types": "*",
|
|
418
|
+
"@peculiar/x509": "^1.14.3",
|
|
419
419
|
"@types/bcryptjs": "^2.4.6",
|
|
420
420
|
"@types/better-sqlite3": "^7.6.13",
|
|
421
421
|
"@types/js-yaml": "^4.0.9",
|