@camstack/system 1.2.141 → 1.2.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addon-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/trigger-engine.d.ts +7 -81
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +29 -109
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +26 -106
- 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-BNhvXrQk.js → dist-CQs1b7uh.js} +838 -78
- package/dist/{dist-6mn3LQvB.mjs → dist-CVuVKA-O.mjs} +803 -79
- package/dist/index.d.ts +3 -0
- package/dist/index.js +127 -3
- package/dist/index.mjs +124 -4
- package/dist/logging/log-manager.d.ts +16 -0
- package/dist/logging/logging-gate.d.ts +32 -0
- package/dist/logging/logging-gate.singleton.d.ts +5 -0
- package/dist/{manifest-python-deps-DBQarwp9.js → manifest-python-deps-B_mCU6gz.js} +25 -2
- package/dist/{manifest-python-deps-D3zYlMEa.mjs → manifest-python-deps-BuhBXCg0.mjs} +25 -2
- package/dist/{retired-settings-keys-SYwVv_Ym.mjs → retired-settings-keys-DnMYSIEr.mjs} +1 -1
- package/dist/{retired-settings-keys-DVgdWTd7.js → retired-settings-keys-Dvei9nhG.js} +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,9 @@ export type { ILogDestination } from './logging/log-manager.js';
|
|
|
57
57
|
export { LogManager } from './logging/log-manager.js';
|
|
58
58
|
export type { LogEntry, LogFilter, LogLevel } from './logging/log-ring-buffer.js';
|
|
59
59
|
export { LogRingBuffer } from './logging/log-ring-buffer.js';
|
|
60
|
+
export type { LevelBearing } from './logging/logging-gate.js';
|
|
61
|
+
export { DEFAULT_LOG_LEVEL, LoggingGate } from './logging/logging-gate.js';
|
|
62
|
+
export { __resetLoggingGateForTests, getLoggingGate, } from './logging/logging-gate.singleton.js';
|
|
60
63
|
export type { IScopedLogger } from './logging/scoped-logger.js';
|
|
61
64
|
export { ScopedLogger } from './logging/scoped-logger.js';
|
|
62
65
|
export type { ClientNetworkStats, DeviceNetworkStats, INetworkQualityTracker, StreamNetworkStats, } from './network/network-quality.js';
|
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-CQs1b7uh.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");
|
|
@@ -26,7 +26,7 @@ require("./builtins/system-config/index.js");
|
|
|
26
26
|
const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
|
|
27
27
|
const require_file_data_plane = require("./file-data-plane-DO8KbxCe.js");
|
|
28
28
|
const require_tls$1 = require("./tls-u8QCJCFE.js");
|
|
29
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
29
|
+
const require_manifest_python_deps = require("./manifest-python-deps-B_mCU6gz.js");
|
|
30
30
|
const require_resource_monitor = require("./resource-monitor-CdnzxBLP.js");
|
|
31
31
|
const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
|
|
32
32
|
let zod = require("zod");
|
|
@@ -696,6 +696,109 @@ var LogRingBuffer = class {
|
|
|
696
696
|
}
|
|
697
697
|
};
|
|
698
698
|
//#endregion
|
|
699
|
+
//#region src/logging/logging-gate.ts
|
|
700
|
+
/**
|
|
701
|
+
* The in-memory MIRROR of the logging settings document, read on the log path.
|
|
702
|
+
*
|
|
703
|
+
* ## Why a mirror and not the settings store
|
|
704
|
+
*
|
|
705
|
+
* The document (`system.getLoggingSettings` / `setLoggingSettings`) is the
|
|
706
|
+
* durable AUTHORITY. It is a row in `system-settings`, reachable only through
|
|
707
|
+
* an async cap call — and this gate is consulted once per emitted log line. A
|
|
708
|
+
* hot path cannot await a store, so the store is mirrored here and the mirror
|
|
709
|
+
* is refreshed OFF the hot path, on a write and once at boot.
|
|
710
|
+
*
|
|
711
|
+
* ## Cost when nothing is set
|
|
712
|
+
*
|
|
713
|
+
* {@link LoggingGate.restrictsDestinations} is a plain boolean FIELD, and it is
|
|
714
|
+
* the FIRST statement of {@link LoggingGate.allowsDestination} — before the
|
|
715
|
+
* entry is touched at all. A default hub sets no level, the field stays
|
|
716
|
+
* `false`, and every line costs one boolean read and a return: no rank lookup,
|
|
717
|
+
* no property access, no allocation. `logging-gate.spec.ts` pins this with an
|
|
718
|
+
* entry whose `level` getter THROWS, so moving the guard below a field access
|
|
719
|
+
* fails the spec instead of taxing every line the hub emits.
|
|
720
|
+
*
|
|
721
|
+
* ## A failed read changes nothing (D49)
|
|
722
|
+
*
|
|
723
|
+
* Nothing here reads the store. The only way the mirror moves is an explicit
|
|
724
|
+
* {@link LoggingGate.setDestinationFloor}, and the service that owns the
|
|
725
|
+
* document calls it ONLY with a value it actually read. A store read that
|
|
726
|
+
* fails leaves the mirror exactly as it was: it neither raises a level nor
|
|
727
|
+
* lowers one, and a diagnostic armed before the failure stays armed.
|
|
728
|
+
*
|
|
729
|
+
* ## What the floor governs, and what it deliberately does not
|
|
730
|
+
*
|
|
731
|
+
* The floor gates the fan-out to DESTINATIONS (console, rotated files, Loki,
|
|
732
|
+
* the hub forwarder). It does NOT gate the in-memory ring buffer: the ring
|
|
733
|
+
* keeps everything it has room for and prunes by level only under pressure,
|
|
734
|
+
* which the plan
|
|
735
|
+
* (`docs/design/plans/2026-08-26-logging-per-componente.md`) settles as the
|
|
736
|
+
* better policy — an admission level for the ring would make the log viewer go
|
|
737
|
+
* blind exactly when an operator raises the level to quieten a disk.
|
|
738
|
+
*
|
|
739
|
+
* A destination's own level still applies on top. The two compose as
|
|
740
|
+
* "most restrictive wins", which is a hierarchy and not a second authority:
|
|
741
|
+
* the floor is node-wide, the destination level is that destination's own, and
|
|
742
|
+
* neither can be read as overriding the other.
|
|
743
|
+
*/
|
|
744
|
+
/** What a hub emits when nothing is configured anywhere. */
|
|
745
|
+
var DEFAULT_LOG_LEVEL = "debug";
|
|
746
|
+
var LoggingGate = class {
|
|
747
|
+
/** The ONLY field an unrestricted log path reads. */
|
|
748
|
+
restricted = false;
|
|
749
|
+
floorRank = require_dist.LOG_LEVEL_RANK[DEFAULT_LOG_LEVEL];
|
|
750
|
+
floor = DEFAULT_LOG_LEVEL;
|
|
751
|
+
/** The effective node-wide level currently mirrored. */
|
|
752
|
+
get destinationFloor() {
|
|
753
|
+
return this.floor;
|
|
754
|
+
}
|
|
755
|
+
/** True only when the mirrored level is stricter than the default. */
|
|
756
|
+
get restrictsDestinations() {
|
|
757
|
+
return this.restricted;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* May this entry be fanned out to the log destinations?
|
|
761
|
+
*
|
|
762
|
+
* The boolean field is read FIRST. Do not move it below anything.
|
|
763
|
+
*/
|
|
764
|
+
allowsDestination(entry) {
|
|
765
|
+
if (!this.restricted) return true;
|
|
766
|
+
return require_dist.LOG_LEVEL_RANK[entry.level] >= this.floorRank;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Refresh the mirror. Called off the hot path — on an operator write and
|
|
770
|
+
* once at boot — and never with a value that was not actually read.
|
|
771
|
+
*/
|
|
772
|
+
setDestinationFloor(level) {
|
|
773
|
+
this.floor = level;
|
|
774
|
+
this.floorRank = require_dist.LOG_LEVEL_RANK[level];
|
|
775
|
+
this.restricted = this.floorRank > require_dist.LOG_LEVEL_RANK[DEFAULT_LOG_LEVEL];
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
//#endregion
|
|
779
|
+
//#region src/logging/logging-gate.singleton.ts
|
|
780
|
+
/**
|
|
781
|
+
* Process-wide holder for the {@link LoggingGate}.
|
|
782
|
+
*
|
|
783
|
+
* Two call sites that never meet need the SAME instance: `LogManager` reads it
|
|
784
|
+
* on every emitted line, and the `system` cap provider — which `trpc.router.ts`
|
|
785
|
+
* rebuilds PER REQUEST — refreshes it whenever the document is written. A gate
|
|
786
|
+
* built inside that per-request factory would be refreshed and collected,
|
|
787
|
+
* which is the shape of a knob that never does anything.
|
|
788
|
+
*
|
|
789
|
+
* Same idiom as `http-request-census.singleton.ts`.
|
|
790
|
+
*/
|
|
791
|
+
var instance = null;
|
|
792
|
+
/** The process-wide logging gate. Created unrestricted on first use. */
|
|
793
|
+
function getLoggingGate() {
|
|
794
|
+
instance ??= new LoggingGate();
|
|
795
|
+
return instance;
|
|
796
|
+
}
|
|
797
|
+
/** Test-only: drop the instance so a spec starts from an unrestricted gate. */
|
|
798
|
+
function __resetLoggingGateForTests() {
|
|
799
|
+
instance = null;
|
|
800
|
+
}
|
|
801
|
+
//#endregion
|
|
699
802
|
//#region src/logging/partitioned-log-buffer.ts
|
|
700
803
|
/** Bucket key for entries that carry no resolvable `addonId` tag. */
|
|
701
804
|
var NO_ADDON_KEY = "";
|
|
@@ -1036,6 +1139,16 @@ var LogManager = class {
|
|
|
1036
1139
|
*/
|
|
1037
1140
|
bootstrapConsole = null;
|
|
1038
1141
|
/**
|
|
1142
|
+
* The node-wide level floor, mirrored from the logging settings document.
|
|
1143
|
+
*
|
|
1144
|
+
* Consulted on EVERY emitted line, so it is a boolean field read and nothing
|
|
1145
|
+
* else while nothing is configured — see {@link LoggingGate}. It gates the
|
|
1146
|
+
* DESTINATIONS only: the ring buffer keeps the line either way, because a
|
|
1147
|
+
* floor that also blinded the log viewer would make raising the level to
|
|
1148
|
+
* quieten a disk cost the operator the one window they read incidents from.
|
|
1149
|
+
*/
|
|
1150
|
+
gate = getLoggingGate();
|
|
1151
|
+
/**
|
|
1039
1152
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
1040
1153
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
1041
1154
|
*
|
|
@@ -1070,7 +1183,7 @@ var LogManager = class {
|
|
|
1070
1183
|
return new ScopedLogger(scope, (entry) => {
|
|
1071
1184
|
const enriched = this.enrichDeviceName(entry);
|
|
1072
1185
|
if (this.isDestinationEnabled?.("log-buffer") !== false) this.ringBuffer.push(enriched);
|
|
1073
|
-
for (const entry of this.destinations) {
|
|
1186
|
+
if (this.gate.allowsDestination(enriched)) for (const entry of this.destinations) {
|
|
1074
1187
|
if (entry.addonId !== void 0 && this.isDestinationEnabled?.(entry.addonId) === false) continue;
|
|
1075
1188
|
entry.dest.write(enriched);
|
|
1076
1189
|
}
|
|
@@ -1135,6 +1248,13 @@ var LogManager = class {
|
|
|
1135
1248
|
reconfigureBuffer(options) {
|
|
1136
1249
|
this.ringBuffer.reconfigure(options);
|
|
1137
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Swap the node-wide level gate. Production uses the process singleton;
|
|
1253
|
+
* a spec passes its own so two suites cannot arm each other's floor.
|
|
1254
|
+
*/
|
|
1255
|
+
setLoggingGate(gate) {
|
|
1256
|
+
this.gate = gate;
|
|
1257
|
+
}
|
|
1138
1258
|
/** Set the per-destination enablement check (see {@link isDestinationEnabled}). */
|
|
1139
1259
|
setDestinationEnabledCheck(check) {
|
|
1140
1260
|
this.isDestinationEnabled = check ?? void 0;
|
|
@@ -95154,6 +95274,7 @@ exports.CoreBlocksAddon = require_builtins_core_blocks_core_blocks_addon.CoreBlo
|
|
|
95154
95274
|
exports.CustomActionRegistry = require_custom_action_registry.CustomActionRegistry;
|
|
95155
95275
|
exports.DEFAULT_DATA_PATH = DEFAULT_DATA_PATH;
|
|
95156
95276
|
exports.DEFAULT_LAN_HTTP_PORT = require_tls$1.DEFAULT_LAN_HTTP_PORT;
|
|
95277
|
+
exports.DEFAULT_LOG_LEVEL = DEFAULT_LOG_LEVEL;
|
|
95157
95278
|
exports.DEVICE_SETTINGS_CONTRIBUTION_METHODS = require_dist.DEVICE_SETTINGS_CONTRIBUTION_METHODS;
|
|
95158
95279
|
exports.DEVICE_STATUS_METHOD = require_dist.DEVICE_STATUS_METHOD;
|
|
95159
95280
|
exports.DataPlaneRegistry = DataPlaneRegistry;
|
|
@@ -95193,6 +95314,7 @@ exports.LocalChildClient = require_manifest_python_deps.LocalChildClient;
|
|
|
95193
95314
|
exports.LocalChildRegistry = require_manifest_python_deps.LocalChildRegistry;
|
|
95194
95315
|
exports.LogManager = LogManager;
|
|
95195
95316
|
exports.LogRingBuffer = LogRingBuffer;
|
|
95317
|
+
exports.LoggingGate = LoggingGate;
|
|
95196
95318
|
exports.LokiDestination = require_builtins_loki_logging_index.LokiDestination$1;
|
|
95197
95319
|
exports.LokiLoggingAddon = require_builtins_loki_logging_index.LokiLoggingAddon$1;
|
|
95198
95320
|
exports.MAX_LEAF_VALIDITY_DAYS = require_tls$1.MAX_LEAF_VALIDITY_DAYS;
|
|
@@ -95243,6 +95365,7 @@ exports.UserManager = require_builtins_local_auth_local_auth_addon.UserManager;
|
|
|
95243
95365
|
exports.WinstonDestination = require_builtins_winston_logging_index.WinstonDestination$1;
|
|
95244
95366
|
exports.WinstonLoggingAddon = require_builtins_winston_logging_index.WinstonLoggingAddon$1;
|
|
95245
95367
|
exports.__resetCapUsageRegistryForTests = require_manifest_python_deps.__resetCapUsageRegistryForTests;
|
|
95368
|
+
exports.__resetLoggingGateForTests = __resetLoggingGateForTests;
|
|
95246
95369
|
exports.adaptBrokerToCluster = require_manifest_python_deps.adaptBrokerToCluster;
|
|
95247
95370
|
exports.addonSettingsCapability = require_dist.addonSettingsCapability;
|
|
95248
95371
|
exports.allFamiliesListenHost = require_tls$1.allFamiliesListenHost;
|
|
@@ -95364,6 +95487,7 @@ Object.defineProperty(exports, "getFfmpegDownloadUrl", {
|
|
|
95364
95487
|
return _camstack_types_node.getFfmpegDownloadUrl;
|
|
95365
95488
|
}
|
|
95366
95489
|
});
|
|
95490
|
+
exports.getLoggingGate = getLoggingGate;
|
|
95367
95491
|
exports.getModelFilePath = require_file_data_plane.getModelFilePath;
|
|
95368
95492
|
exports.getMoleculerEventStats = require_manifest_python_deps.getMoleculerEventStats;
|
|
95369
95493
|
exports.getOrInitReadinessRegistry = require_manifest_python_deps.getOrInitReadinessRegistry;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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 {
|
|
2
|
+
import { $ as kebabToCamel, Bt as emitDownForOwnedCaps, C as addonSettingsCapability, Dt as DATAPLANE_SECRET_HEADER$1, G as extractNestedAddonId, Ht as expandCapMethods, It as asJsonObject$1, J as isCollectionArrayMethod, Jt as readinessKey, Kt as parseJsonObject, Lt as asNumber, Nt as ReadinessRegistry, Ot as DEVICE_SETTINGS_CONTRIBUTION_METHODS, Pt as ReadinessTimeoutError, Q as isVoidInput, Qt as EventCategory$1, Rt as asString$1, Tt as errMsg$1, Xt as scopeKey, Y as isObjectInput, Yt as resolveCapMount, dt as resolveMethodAuth, et as lifecycleJobSchema, f as LOG_LEVEL_RANK, it as looseSchema, kt as DEVICE_STATUS_METHOD, m as RUNTIME_DEFAULTS, mt as scopesAllowDeviceCap, p as METHOD_ACCESS_MAP, pt as scopesAllowAddon, q as isArrayOutputSchema, qt as parseJsonUnknown$1, rt as logLevelAtMost, st as objectInputDeclaresAddonId, t as ALL_CAPABILITY_DEFINITIONS, ut as procedureAuthKey, zt as createEvent } from "./dist-CVuVKA-O.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";
|
|
@@ -25,7 +25,7 @@ import "./builtins/system-config/index.mjs";
|
|
|
25
25
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
26
26
|
import { a as parseTokenizedUrl, c as collectModelFiles, d as downloadModel, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, o as resolveFilePath, p as fetchJson, r as createAuthenticatedFileServer, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-BhKdxJgf.mjs";
|
|
27
27
|
import { C as registerLanHttpHandler, S as readLanHttpState, _ as DEFAULT_LAN_HTTP_PORT, a as writeTlsMode, b as bindPendingLanHttp, c as loadTlsCert, d as collectCertIdentity, f as CA_VALIDITY_DAYS, g as evaluateExistingCert, h as SERVER_AUTH_OID, i as writeExtraSans, l as reissueTlsLeaf, m as MAX_LEAF_VALIDITY_DAYS, n as readTlsAccessStatus, o as validateUploadedTls, p as LEAF_RENEWAL_WINDOW_DAYS, r as readTlsMode, s as ensureTlsCert, t as readExtraSans, u as CA_COMMON_NAME, v as allFamiliesListenHost, x as closeLanHttp, y as applyLanHttp } from "./tls-CQhPGSJm.mjs";
|
|
28
|
-
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, At as createV8Reclaimer, B as AGENT_CAP_FWD_SERVICE, C as brokerTransportLink, Ct as createAddonDataPlaneFacility, D as HUB_CAP_FWD_ACTION, Dt as HEAP_WATCH_WARN_RATIO, E as localProviderLink, Et as HEAP_WATCH_INTERVAL_MS, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, Mt as startHeapWatch, N as udsChildLogToWorkerEntry, Nt as startRunnerHeapWatch, O as HUB_CAP_FWD_SERVICE, Ot as RUNNER_HEAP_WATCH_INTERVAL_MS, P as createUdsLogger, Pt as strandedMb, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerCallForCap, St as runNpm, T as ipcParentLink, Tt as HEAP_RECLAIM_TRIGGER_MB, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as createKernelHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as __resetCapUsageRegistryForTests, bt as resolveAddonClass, c as setHubConnected, ct as capActionName, d as getBrokerEventBus, dt as capServiceName, et as createBrokerDeviceManagerApi, f as getMoleculerEventStats, ft as parseCapAction, g as AddonDepsManager, gt as CapabilityHandle, h as subscribePassthrough, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, jt as shouldReclaim, k as createHubCapForwardService, kt as buildHeapSample, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as setNodeEventInterest, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as registerEventBusService, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as clusterEventTopic, ut as capBareAction, v as resolveHwAccel, vt as copyBundledNativeModules, w as buildLinkChain, wt as HEAP_RECLAIM_MIN_INTERVAL_MS, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as installManifestNativeDeps, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-
|
|
28
|
+
import { $ as buildUdsNativeCapProxy, A as createParentUnownedCallHandler, At as createV8Reclaimer, B as AGENT_CAP_FWD_SERVICE, C as brokerTransportLink, Ct as createAddonDataPlaneFacility, D as HUB_CAP_FWD_ACTION, Dt as HEAP_WATCH_WARN_RATIO, E as localProviderLink, Et as HEAP_WATCH_INTERVAL_MS, F as createUdsLoggerWithControl, G as createLocalTransport, H as CapRouteError, I as LocalChildClient, J as SocketChannel, K as UdsLocalTransportClient, L as LocalChildRegistry, M as createUdsEventBus, Mt as startHeapWatch, N as udsChildLogToWorkerEntry, Nt as startRunnerHeapWatch, O as HUB_CAP_FWD_SERVICE, Ot as RUNNER_HEAP_WATCH_INTERVAL_MS, P as createUdsLogger, Pt as strandedMb, Q as buildNativeCapProxy, R as UDS_NO_ROUTE_PREFIX, S as brokerCallForCap, St as runNpm, T as ipcParentLink, Tt as HEAP_RECLAIM_TRIGGER_MB, U as classifyCapRoute, V as CapRouteResolver, W as callWithServiceDiscovery, X as FrameDecoder, Y as localEndpointPath, Z as encodeFrame, _ as createKernelHwAccel, _t as CapabilityUnavailableError, a as getWorkerDeviceRegistry, at as createAddonService, b as __resetCapUsageRegistryForTests, bt as resolveAddonClass, c as setHubConnected, ct as capActionName, d as getBrokerEventBus, dt as capServiceName, et as createBrokerDeviceManagerApi, f as getMoleculerEventStats, ft as parseCapAction, g as AddonDepsManager, gt as CapabilityHandle, h as subscribePassthrough, ht as DeviceRegistry, i as createUdsAddonContext, j as createUdsEventBridge, jt as shouldReclaim, k as createHubCapForwardService, kt as buildHeapSample, l as EVENT_TOPIC_PREFIX, lt as capActionSuffix, m as setNodeEventInterest, mt as serializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as validateProviderRegistrations, p as registerEventBusService, pt as deserializeTypedArrays, q as UdsLocalTransportServer, r as createAddonContext, rt as mountNativeCapService, s as getOrInitReadinessRegistryForClient, st as NATIVE_PROVIDER_SERVICE_INFIX, t as installManifestPythonDeps, u as clusterEventTopic, ut as capBareAction, v as resolveHwAccel, vt as copyBundledNativeModules, w as buildLinkChain, wt as HEAP_RECLAIM_MIN_INTERVAL_MS, x as getCapUsageRegistry, xt as resolveNpmInvocation, y as CapUsageRegistry, yt as installManifestNativeDeps, z as AGENT_CAP_FWD_ACTION } from "./manifest-python-deps-BuhBXCg0.mjs";
|
|
29
29
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BWmQ5i-o.mjs";
|
|
30
30
|
import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
|
|
31
31
|
import { z } from "zod";
|
|
@@ -689,6 +689,109 @@ var LogRingBuffer = class {
|
|
|
689
689
|
}
|
|
690
690
|
};
|
|
691
691
|
//#endregion
|
|
692
|
+
//#region src/logging/logging-gate.ts
|
|
693
|
+
/**
|
|
694
|
+
* The in-memory MIRROR of the logging settings document, read on the log path.
|
|
695
|
+
*
|
|
696
|
+
* ## Why a mirror and not the settings store
|
|
697
|
+
*
|
|
698
|
+
* The document (`system.getLoggingSettings` / `setLoggingSettings`) is the
|
|
699
|
+
* durable AUTHORITY. It is a row in `system-settings`, reachable only through
|
|
700
|
+
* an async cap call — and this gate is consulted once per emitted log line. A
|
|
701
|
+
* hot path cannot await a store, so the store is mirrored here and the mirror
|
|
702
|
+
* is refreshed OFF the hot path, on a write and once at boot.
|
|
703
|
+
*
|
|
704
|
+
* ## Cost when nothing is set
|
|
705
|
+
*
|
|
706
|
+
* {@link LoggingGate.restrictsDestinations} is a plain boolean FIELD, and it is
|
|
707
|
+
* the FIRST statement of {@link LoggingGate.allowsDestination} — before the
|
|
708
|
+
* entry is touched at all. A default hub sets no level, the field stays
|
|
709
|
+
* `false`, and every line costs one boolean read and a return: no rank lookup,
|
|
710
|
+
* no property access, no allocation. `logging-gate.spec.ts` pins this with an
|
|
711
|
+
* entry whose `level` getter THROWS, so moving the guard below a field access
|
|
712
|
+
* fails the spec instead of taxing every line the hub emits.
|
|
713
|
+
*
|
|
714
|
+
* ## A failed read changes nothing (D49)
|
|
715
|
+
*
|
|
716
|
+
* Nothing here reads the store. The only way the mirror moves is an explicit
|
|
717
|
+
* {@link LoggingGate.setDestinationFloor}, and the service that owns the
|
|
718
|
+
* document calls it ONLY with a value it actually read. A store read that
|
|
719
|
+
* fails leaves the mirror exactly as it was: it neither raises a level nor
|
|
720
|
+
* lowers one, and a diagnostic armed before the failure stays armed.
|
|
721
|
+
*
|
|
722
|
+
* ## What the floor governs, and what it deliberately does not
|
|
723
|
+
*
|
|
724
|
+
* The floor gates the fan-out to DESTINATIONS (console, rotated files, Loki,
|
|
725
|
+
* the hub forwarder). It does NOT gate the in-memory ring buffer: the ring
|
|
726
|
+
* keeps everything it has room for and prunes by level only under pressure,
|
|
727
|
+
* which the plan
|
|
728
|
+
* (`docs/design/plans/2026-08-26-logging-per-componente.md`) settles as the
|
|
729
|
+
* better policy — an admission level for the ring would make the log viewer go
|
|
730
|
+
* blind exactly when an operator raises the level to quieten a disk.
|
|
731
|
+
*
|
|
732
|
+
* A destination's own level still applies on top. The two compose as
|
|
733
|
+
* "most restrictive wins", which is a hierarchy and not a second authority:
|
|
734
|
+
* the floor is node-wide, the destination level is that destination's own, and
|
|
735
|
+
* neither can be read as overriding the other.
|
|
736
|
+
*/
|
|
737
|
+
/** What a hub emits when nothing is configured anywhere. */
|
|
738
|
+
var DEFAULT_LOG_LEVEL = "debug";
|
|
739
|
+
var LoggingGate = class {
|
|
740
|
+
/** The ONLY field an unrestricted log path reads. */
|
|
741
|
+
restricted = false;
|
|
742
|
+
floorRank = LOG_LEVEL_RANK[DEFAULT_LOG_LEVEL];
|
|
743
|
+
floor = DEFAULT_LOG_LEVEL;
|
|
744
|
+
/** The effective node-wide level currently mirrored. */
|
|
745
|
+
get destinationFloor() {
|
|
746
|
+
return this.floor;
|
|
747
|
+
}
|
|
748
|
+
/** True only when the mirrored level is stricter than the default. */
|
|
749
|
+
get restrictsDestinations() {
|
|
750
|
+
return this.restricted;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* May this entry be fanned out to the log destinations?
|
|
754
|
+
*
|
|
755
|
+
* The boolean field is read FIRST. Do not move it below anything.
|
|
756
|
+
*/
|
|
757
|
+
allowsDestination(entry) {
|
|
758
|
+
if (!this.restricted) return true;
|
|
759
|
+
return LOG_LEVEL_RANK[entry.level] >= this.floorRank;
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Refresh the mirror. Called off the hot path — on an operator write and
|
|
763
|
+
* once at boot — and never with a value that was not actually read.
|
|
764
|
+
*/
|
|
765
|
+
setDestinationFloor(level) {
|
|
766
|
+
this.floor = level;
|
|
767
|
+
this.floorRank = LOG_LEVEL_RANK[level];
|
|
768
|
+
this.restricted = this.floorRank > LOG_LEVEL_RANK[DEFAULT_LOG_LEVEL];
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
//#endregion
|
|
772
|
+
//#region src/logging/logging-gate.singleton.ts
|
|
773
|
+
/**
|
|
774
|
+
* Process-wide holder for the {@link LoggingGate}.
|
|
775
|
+
*
|
|
776
|
+
* Two call sites that never meet need the SAME instance: `LogManager` reads it
|
|
777
|
+
* on every emitted line, and the `system` cap provider — which `trpc.router.ts`
|
|
778
|
+
* rebuilds PER REQUEST — refreshes it whenever the document is written. A gate
|
|
779
|
+
* built inside that per-request factory would be refreshed and collected,
|
|
780
|
+
* which is the shape of a knob that never does anything.
|
|
781
|
+
*
|
|
782
|
+
* Same idiom as `http-request-census.singleton.ts`.
|
|
783
|
+
*/
|
|
784
|
+
var instance = null;
|
|
785
|
+
/** The process-wide logging gate. Created unrestricted on first use. */
|
|
786
|
+
function getLoggingGate() {
|
|
787
|
+
instance ??= new LoggingGate();
|
|
788
|
+
return instance;
|
|
789
|
+
}
|
|
790
|
+
/** Test-only: drop the instance so a spec starts from an unrestricted gate. */
|
|
791
|
+
function __resetLoggingGateForTests() {
|
|
792
|
+
instance = null;
|
|
793
|
+
}
|
|
794
|
+
//#endregion
|
|
692
795
|
//#region src/logging/partitioned-log-buffer.ts
|
|
693
796
|
/** Bucket key for entries that carry no resolvable `addonId` tag. */
|
|
694
797
|
var NO_ADDON_KEY = "";
|
|
@@ -1029,6 +1132,16 @@ var LogManager = class {
|
|
|
1029
1132
|
*/
|
|
1030
1133
|
bootstrapConsole = null;
|
|
1031
1134
|
/**
|
|
1135
|
+
* The node-wide level floor, mirrored from the logging settings document.
|
|
1136
|
+
*
|
|
1137
|
+
* Consulted on EVERY emitted line, so it is a boolean field read and nothing
|
|
1138
|
+
* else while nothing is configured — see {@link LoggingGate}. It gates the
|
|
1139
|
+
* DESTINATIONS only: the ring buffer keeps the line either way, because a
|
|
1140
|
+
* floor that also blinded the log viewer would make raising the level to
|
|
1141
|
+
* quieten a disk cost the operator the one window they read incidents from.
|
|
1142
|
+
*/
|
|
1143
|
+
gate = getLoggingGate();
|
|
1144
|
+
/**
|
|
1032
1145
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
1033
1146
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
1034
1147
|
*
|
|
@@ -1063,7 +1176,7 @@ var LogManager = class {
|
|
|
1063
1176
|
return new ScopedLogger(scope, (entry) => {
|
|
1064
1177
|
const enriched = this.enrichDeviceName(entry);
|
|
1065
1178
|
if (this.isDestinationEnabled?.("log-buffer") !== false) this.ringBuffer.push(enriched);
|
|
1066
|
-
for (const entry of this.destinations) {
|
|
1179
|
+
if (this.gate.allowsDestination(enriched)) for (const entry of this.destinations) {
|
|
1067
1180
|
if (entry.addonId !== void 0 && this.isDestinationEnabled?.(entry.addonId) === false) continue;
|
|
1068
1181
|
entry.dest.write(enriched);
|
|
1069
1182
|
}
|
|
@@ -1128,6 +1241,13 @@ var LogManager = class {
|
|
|
1128
1241
|
reconfigureBuffer(options) {
|
|
1129
1242
|
this.ringBuffer.reconfigure(options);
|
|
1130
1243
|
}
|
|
1244
|
+
/**
|
|
1245
|
+
* Swap the node-wide level gate. Production uses the process singleton;
|
|
1246
|
+
* a spec passes its own so two suites cannot arm each other's floor.
|
|
1247
|
+
*/
|
|
1248
|
+
setLoggingGate(gate) {
|
|
1249
|
+
this.gate = gate;
|
|
1250
|
+
}
|
|
1131
1251
|
/** Set the per-destination enablement check (see {@link isDestinationEnabled}). */
|
|
1132
1252
|
setDestinationEnabledCheck(check) {
|
|
1133
1253
|
this.isDestinationEnabled = check ?? void 0;
|
|
@@ -95113,4 +95233,4 @@ var LifecycleJobEngine = class {
|
|
|
95113
95233
|
}
|
|
95114
95234
|
};
|
|
95115
95235
|
//#endregion
|
|
95116
|
-
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, 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, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, 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_TRIGGER_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LokiDestination, LokiLoggingAddon, MAX_LEAF_VALIDITY_DAYS, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, 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, __resetCapUsageRegistryForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createDoorSettingsView, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readLanHttpState, readPendingRestart, readTlsAccessStatus, readTlsMode, readinessKey, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runHubAddonBoot, runNpm, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, serializeTypedArrays, setHubConnected, setNodeEventInterest, shouldReclaim, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
95236
|
+
export { AGENT_CAP_FWD_ACTION, AGENT_CAP_FWD_SERVICE, AGENT_READINESS_SERVICE_NAME, ALL_CAPABILITY_DEFINITIONS, AddonApiFactory, AddonDepsManager, AddonEngineManager, AddonHealthMonitor, AddonInstaller, AddonLoader, AddonManifest, AddonRouteRegistry, AlertCenterAddon, ApiKeyManager, AuthManager, 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, DEFAULT_DATA_PATH, DEFAULT_LAN_HTTP_PORT, DEFAULT_LOG_LEVEL, DEVICE_SETTINGS_CONTRIBUTION_METHODS, DEVICE_STATUS_METHOD, DataPlaneRegistry, DeviceManagerAddon, DeviceRegistry, DeviceStore, 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_TRIGGER_MB, HEAP_WATCH_INTERVAL_MS, HEAP_WATCH_WARN_RATIO, HUB_CAP_FWD_ACTION, HUB_CAP_FWD_SERVICE, HubForwarderAddon, HubForwarderDestination, HubLogForwarder, HubNodeRegistry, INFRA_CAPABILITIES, IntegrationRegistry, JobJournal, LEAF_RENEWAL_WINDOW_DAYS, LifecycleJobEngine, LifecycleStateMachine, LivenessMonitorAddon, LocalAuthAddon, LocalChildClient, LocalChildRegistry, LogManager, LogRingBuffer, LoggingGate, LokiDestination, LokiLoggingAddon, MAX_LEAF_VALIDITY_DAYS, METHOD_ACCESS_MAP, ModelDownloadService, NATIVE_PROVIDER_SERVICE_INFIX, NATIVE_SCAN_DEPTH, NativeMetricsAddon, NativeMetricsProvider, NetworkQualityTracker, NotificationService, PYTHON_VERSION, PipelineRunner, PipelineValidator, PythonEnvManager, QUARANTINE_DIRNAME, RESTART_MARKER_FILE, RUNNER_HEAP_WATCH_INTERVAL_MS, RUNTIME_DEFAULTS, ReadinessRegistry, ReadinessTimeoutError, ReplEngine, RingBuffer, SERVER_AUTH_OID, 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, __resetCapUsageRegistryForTests, __resetLoggingGateForTests, adaptBrokerToCluster, addonSettingsCapability, allFamiliesListenHost, applyLanHttp, bindPendingLanHttp, bootstrapSchema, brokerCallForCap, brokerTransportLink, buildBinaryPath, buildCapRouters, buildHeapSample, buildLinkChain, buildNativeCapProxy, buildNodeManifest, buildStorageLocationRegistry, buildUdsNativeCapProxy, builderMountedCapNames, callRegisterNodeWithRetry, callWithServiceDiscovery, canServeDataPlane, capActionName, capActionSuffix, capBareAction, capServiceName, classifyAddonDir, classifyCapRoute, clearPendingRestart, closeLanHttp, clusterEventTopic, clusterSecretMatches, collectCertIdentity, collectModelFiles, contentTypeFor, copyDirRecursive, copyExtraFileDirs, createAddonContext, createAddonDataPlaneFacility, createAddonService, createAuthenticatedFileServer, createBroker, createBrokerDeviceManagerApi, createCoreCapService, createDoorSettingsView, createFileDataPlaneHandler, createHubCapForwardService, createHubService, createKernelHwAccel, createLocalTransport, createParentUnownedCallHandler, createProcessService, createReadinessService, createReadinessServiceForRegistry, createScopedProcessManager, createStreamProbeBrokerService, createUdsAddonContext, createUdsEventBridge, createUdsEventBus, createUdsLogger, createUdsLoggerWithControl, createV8Reclaimer, deleteModelFromDisk, deriveAgentListenPort, describeProviderKindDrift, detectWorkspacePackagesDir, downloadBinary, downloadFile, downloadModel, emitDownForOwnedCaps, encodeFrame, ensureAddonNativePrebuilds, ensureBinary, ensureDir, ensureFfmpeg, ensureLibraryBuilt, ensureModel, ensureNativePrebuilds, ensurePython, ensureTlsCert, evaluateExistingCert, expandCapMethods, fetchJson, findInPath, formatLogLine, getBrokerEventBus, getCapUsageRegistry, getFfmpegDownloadUrl, getLoggingGate, getModelFilePath, getMoleculerEventStats, getOrInitReadinessRegistry, getOrInitReadinessRegistryForClient, getPidStats, getPlatformInfo, getPythonDownloadUrl, getRestartMarkerPath, getSinglePidStats, getWorkerDeviceRegistry, hasDotNode, hashClusterSecret, installManifestNativeDeps, installManifestPythonDeps, installPackageFromNpm, installPythonPackages, installPythonRequirements, ipcParentLink, isAddonDeploySource, isArrayOutputSchema, isClusterSecretMismatchError, isCollectionArrayMethod, isInfraCapability, isModelDownloaded, isSourceNewer, isolatedBuiltinPhase, loadTlsCert, localEndpointPath, localProviderLink, mountNativeCapService, parseCapAction, parseRangeHeader, parseTokenizedUrl, partitionIsolatedBuiltinIds, proxyToUpstream, quarantineAddonResidue, readExtraSans, readLanHttpState, readPendingRestart, readTlsAccessStatus, readTlsMode, readinessKey, registerEventBusService, registerLanHttpHandler, reissueTlsLeaf, resolveFilePath, resolveHwAccel, resolveNpmInvocation, runHubAddonBoot, runNpm, scheduleSelfRestart, scopeKey, scopesAllowAddon, scopesAllowDeviceCap, selectAddonResidue, serializeTypedArrays, setHubConnected, setNodeEventInterest, shouldReclaim, startHeapWatch, startRunnerHeapWatch, strandedMb, stripCamstackDeps, subscribePassthrough, udsChildLogToWorkerEntry, validateProviderRegistrations, validateUploadedTls, waitUntilReady, writeExtraSans, writePendingRestart, writeTlsMode };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LogEntry, LogFilter, LogLevel } from './log-ring-buffer.js';
|
|
2
|
+
import { LoggingGate } from './logging-gate.js';
|
|
2
3
|
import { PartitionedLogBufferOptions } from './partitioned-log-buffer.js';
|
|
3
4
|
import { IScopedLogger } from './scoped-logger.js';
|
|
4
5
|
export interface ILogDestination {
|
|
@@ -50,6 +51,16 @@ export declare class LogManager {
|
|
|
50
51
|
* replay suppressed — when {@link STDOUT_DESTINATION_ADDON_ID} registers.
|
|
51
52
|
*/
|
|
52
53
|
private bootstrapConsole;
|
|
54
|
+
/**
|
|
55
|
+
* The node-wide level floor, mirrored from the logging settings document.
|
|
56
|
+
*
|
|
57
|
+
* Consulted on EVERY emitted line, so it is a boolean field read and nothing
|
|
58
|
+
* else while nothing is configured — see {@link LoggingGate}. It gates the
|
|
59
|
+
* DESTINATIONS only: the ring buffer keeps the line either way, because a
|
|
60
|
+
* floor that also blinded the log viewer would make raising the level to
|
|
61
|
+
* quieten a disk cost the operator the one window they read incidents from.
|
|
62
|
+
*/
|
|
63
|
+
private gate;
|
|
53
64
|
/**
|
|
54
65
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
55
66
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
@@ -94,6 +105,11 @@ export declare class LogManager {
|
|
|
94
105
|
readonly maxTotalEntries?: number | null;
|
|
95
106
|
readonly pruneLevel?: LogLevel;
|
|
96
107
|
}): void;
|
|
108
|
+
/**
|
|
109
|
+
* Swap the node-wide level gate. Production uses the process singleton;
|
|
110
|
+
* a spec passes its own so two suites cannot arm each other's floor.
|
|
111
|
+
*/
|
|
112
|
+
setLoggingGate(gate: LoggingGate): void;
|
|
97
113
|
/** Set the per-destination enablement check (see {@link isDestinationEnabled}). */
|
|
98
114
|
setDestinationEnabledCheck(check: ((addonId: string) => boolean) | null): void;
|
|
99
115
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { LogLevel } from '@camstack/types';
|
|
2
|
+
/** What a hub emits when nothing is configured anywhere. */
|
|
3
|
+
export declare const DEFAULT_LOG_LEVEL: LogLevel;
|
|
4
|
+
/**
|
|
5
|
+
* The only thing the gate needs off an entry — and it must not read it while
|
|
6
|
+
* the gate is unrestricted. Deliberately structural so the spec can hand in an
|
|
7
|
+
* object whose getter throws.
|
|
8
|
+
*/
|
|
9
|
+
export interface LevelBearing {
|
|
10
|
+
readonly level: LogLevel;
|
|
11
|
+
}
|
|
12
|
+
export declare class LoggingGate {
|
|
13
|
+
/** The ONLY field an unrestricted log path reads. */
|
|
14
|
+
private restricted;
|
|
15
|
+
private floorRank;
|
|
16
|
+
private floor;
|
|
17
|
+
/** The effective node-wide level currently mirrored. */
|
|
18
|
+
get destinationFloor(): LogLevel;
|
|
19
|
+
/** True only when the mirrored level is stricter than the default. */
|
|
20
|
+
get restrictsDestinations(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* May this entry be fanned out to the log destinations?
|
|
23
|
+
*
|
|
24
|
+
* The boolean field is read FIRST. Do not move it below anything.
|
|
25
|
+
*/
|
|
26
|
+
allowsDestination(entry: LevelBearing): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Refresh the mirror. Called off the hot path — on an operator write and
|
|
29
|
+
* once at boot — and never with a value that was not actually read.
|
|
30
|
+
*/
|
|
31
|
+
setDestinationFloor(level: LogLevel): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LoggingGate } from './logging-gate.js';
|
|
2
|
+
/** The process-wide logging gate. Created unrestricted on first use. */
|
|
3
|
+
export declare function getLoggingGate(): LoggingGate;
|
|
4
|
+
/** Test-only: drop the instance so a spec starts from an unrestricted gate. */
|
|
5
|
+
export declare function __resetLoggingGateForTests(): void;
|
|
@@ -7893,11 +7893,34 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
7893
7893
|
};
|
|
7894
7894
|
/**
|
|
7895
7895
|
* Soft read for CONSUMERS: a failure reads as empty so a boot path degrades
|
|
7896
|
-
* to defaults instead of throwing.
|
|
7897
|
-
*
|
|
7896
|
+
* to defaults instead of throwing. The degradation is never SILENT — a
|
|
7897
|
+
* consumer that got `{}` because the store did not answer looks identical to
|
|
7898
|
+
* one whose store is genuinely empty, and downstream that difference decides
|
|
7899
|
+
* whether an addon runs on the operator's configuration or on its
|
|
7900
|
+
* constructor defaults.
|
|
7901
|
+
*
|
|
7902
|
+
* "Safe because the result is never written back" is what this docblock used
|
|
7903
|
+
* to claim, and it was a leftover that read as verification.
|
|
7904
|
+
* `BaseAddon.resolveConfig` reads THIS function through
|
|
7905
|
+
* `ctx.settings.readAddonStore()`; the defaults it falls back to then become
|
|
7906
|
+
* the values the addon's next `updateGlobalSettings` patch carries into the
|
|
7907
|
+
* store. That is how the Home Assistant export lost its membership on
|
|
7908
|
+
* 2026-08-24 — see `brokerRefreshPatch` in the ha-export addon for the other
|
|
7909
|
+
* half of that story. The line below is the only warning that this window is
|
|
7910
|
+
* open at all.
|
|
7898
7911
|
*/
|
|
7899
7912
|
const readBlob = async (coll, key, namespace) => {
|
|
7900
7913
|
const r = await readBlobResult(coll, key, namespace);
|
|
7914
|
+
if (r.kind === "failed") {
|
|
7915
|
+
scopedLogger.error(`settings read FAILED (${coll}/${key}) — answering empty, this caller now sees DEFAULTS`, { meta: {
|
|
7916
|
+
addonId,
|
|
7917
|
+
collection: coll,
|
|
7918
|
+
key,
|
|
7919
|
+
namespace,
|
|
7920
|
+
error: r.error
|
|
7921
|
+
} });
|
|
7922
|
+
return {};
|
|
7923
|
+
}
|
|
7901
7924
|
return r.kind === "value" ? r.value : {};
|
|
7902
7925
|
};
|
|
7903
7926
|
/** Read-modify-write that REFUSES to write when the read failed. */
|
|
@@ -7889,11 +7889,34 @@ async function buildAddonContext(runtime, declaration, dataDir, options) {
|
|
|
7889
7889
|
};
|
|
7890
7890
|
/**
|
|
7891
7891
|
* Soft read for CONSUMERS: a failure reads as empty so a boot path degrades
|
|
7892
|
-
* to defaults instead of throwing.
|
|
7893
|
-
*
|
|
7892
|
+
* to defaults instead of throwing. The degradation is never SILENT — a
|
|
7893
|
+
* consumer that got `{}` because the store did not answer looks identical to
|
|
7894
|
+
* one whose store is genuinely empty, and downstream that difference decides
|
|
7895
|
+
* whether an addon runs on the operator's configuration or on its
|
|
7896
|
+
* constructor defaults.
|
|
7897
|
+
*
|
|
7898
|
+
* "Safe because the result is never written back" is what this docblock used
|
|
7899
|
+
* to claim, and it was a leftover that read as verification.
|
|
7900
|
+
* `BaseAddon.resolveConfig` reads THIS function through
|
|
7901
|
+
* `ctx.settings.readAddonStore()`; the defaults it falls back to then become
|
|
7902
|
+
* the values the addon's next `updateGlobalSettings` patch carries into the
|
|
7903
|
+
* store. That is how the Home Assistant export lost its membership on
|
|
7904
|
+
* 2026-08-24 — see `brokerRefreshPatch` in the ha-export addon for the other
|
|
7905
|
+
* half of that story. The line below is the only warning that this window is
|
|
7906
|
+
* open at all.
|
|
7894
7907
|
*/
|
|
7895
7908
|
const readBlob = async (coll, key, namespace) => {
|
|
7896
7909
|
const r = await readBlobResult(coll, key, namespace);
|
|
7910
|
+
if (r.kind === "failed") {
|
|
7911
|
+
scopedLogger.error(`settings read FAILED (${coll}/${key}) — answering empty, this caller now sees DEFAULTS`, { meta: {
|
|
7912
|
+
addonId,
|
|
7913
|
+
collection: coll,
|
|
7914
|
+
key,
|
|
7915
|
+
namespace,
|
|
7916
|
+
error: r.error
|
|
7917
|
+
} });
|
|
7918
|
+
return {};
|
|
7919
|
+
}
|
|
7897
7920
|
return r.kind === "value" ? r.value : {};
|
|
7898
7921
|
};
|
|
7899
7922
|
/** Read-modify-write that REFUSES to write when the read failed. */
|