@camstack/system 1.2.455 → 1.2.457
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 +96 -10
- package/dist/addon-runner.mjs +96 -10
- package/dist/{agent-https-CLWrOO3o.mjs → agent-https-CK9Z4sSR.mjs} +32 -5
- package/dist/{agent-https-CCvlRQKV.js → agent-https-CoyOZ3pC.js} +37 -4
- package/dist/auth/auth-manager.d.ts +9 -0
- package/dist/auth/legacy-token-tables.d.ts +16 -0
- package/dist/auth/user-management-internal.d.ts +9 -28
- 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 +2 -2
- package/dist/builtins/alerts/alerts.addon.mjs +2 -2
- 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 +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/console-destination.d.ts +1 -2
- package/dist/builtins/console-logging/index.js +1 -4
- package/dist/builtins/console-logging/index.mjs +1 -4
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
- package/dist/builtins/device-history/capture/capture-engine.d.ts +6 -0
- package/dist/builtins/device-history/device-history.addon.js +441 -83
- package/dist/builtins/device-history/device-history.addon.mjs +441 -83
- package/dist/builtins/device-history/query/history-query.d.ts +35 -9
- package/dist/builtins/device-history/query/point-shape.d.ts +33 -0
- package/dist/builtins/device-history/retention/retention.d.ts +1 -1
- package/dist/builtins/device-history/rollup/rollup-engine.d.ts +2 -0
- package/dist/builtins/device-history/rollup/rollup-math.d.ts +6 -0
- package/dist/builtins/device-history/store/history-store.d.ts +7 -0
- package/dist/builtins/device-history/store/series-registry.d.ts +26 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +1 -2
- package/dist/builtins/hub-forwarder/index.js +1 -4
- package/dist/builtins/hub-forwarder/index.mjs +1 -4
- package/dist/builtins/keychain/index.js +4 -4
- package/dist/builtins/keychain/index.mjs +4 -4
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/auth-schema.d.ts +4 -7
- package/dist/builtins/local-auth/local-auth.addon.d.ts +7 -8
- package/dist/builtins/local-auth/local-auth.addon.js +1086 -1329
- package/dist/builtins/local-auth/local-auth.addon.mjs +1085 -1326
- package/dist/builtins/local-auth/preferences-record-kinds.d.ts +27 -0
- package/dist/builtins/local-auth/record-kinds.d.ts +4 -3
- package/dist/builtins/local-auth/user-preferences-store.d.ts +56 -0
- package/dist/builtins/local-network/local-network.addon.d.ts +8 -0
- package/dist/builtins/local-network/local-network.addon.js +30 -5
- package/dist/builtins/local-network/local-network.addon.mjs +30 -5
- package/dist/builtins/loki-logging/index.js +323 -7
- package/dist/builtins/loki-logging/index.mjs +323 -7
- package/dist/builtins/loki-logging/loki-destination.d.ts +20 -3
- package/dist/builtins/loki-logging/loki-read.d.ts +51 -0
- package/dist/builtins/native-metrics/native-metrics.addon.js +290 -112
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +290 -112
- package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +106 -35
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/record-entries/index.js +1 -1
- package/dist/builtins/record-entries/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/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/records/records-engine-types.d.ts +1 -0
- package/dist/builtins/sqlite-storage/records/records-provider.d.ts +13 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +52 -6
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +52 -6
- package/dist/builtins/storage-orchestrator/location-history-recorder.d.ts +76 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +9 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +144 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +144 -1
- package/dist/builtins/system-config/system-config.addon.js +3 -3
- package/dist/builtins/system-config/system-config.addon.mjs +3 -3
- package/dist/builtins/winston-logging/index.js +165 -3
- package/dist/builtins/winston-logging/index.mjs +165 -3
- package/dist/builtins/winston-logging/log-file-cursor.d.ts +12 -0
- package/dist/builtins/winston-logging/log-file-index-store.d.ts +11 -0
- package/dist/builtins/winston-logging/log-file-index.d.ts +77 -0
- package/dist/builtins/winston-logging/log-file-read-client.d.ts +44 -0
- package/dist/builtins/winston-logging/log-file-read-protocol.d.ts +41 -0
- package/dist/builtins/winston-logging/log-file-read-worker.d.ts +1 -0
- package/dist/builtins/winston-logging/log-file-reader.d.ts +51 -0
- package/dist/builtins/winston-logging/winston-destination.d.ts +20 -2
- package/dist/{composition-sources-CSzD5_qX.mjs → composition-sources-B_jeZDRJ.mjs} +1 -1
- package/dist/{composition-sources-BxUkLNSo.js → composition-sources-qKyvMAvc.js} +1 -1
- package/dist/{constants-DruwCkfp.js → constants-B_X9cWEK.js} +1 -1
- package/dist/{constants-DOlYt1t1.mjs → constants-cxKcZRMi.mjs} +1 -1
- package/dist/{device-ca-uFbTyY_o.mjs → device-ca-BB6nHAL5.mjs} +1 -1
- package/dist/{device-ca-QPBgfqVY.js → device-ca-CVK3YcR_.js} +1 -1
- package/dist/{dist-DjQ8C-ku.js → dist-C89nqNnn.js} +721 -154
- package/dist/{dist-BpSENkRJ.mjs → dist-Dhux90yB.mjs} +668 -155
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-DlgkFJVY.mjs → hub-mdns-ciao-B8olZqqd.mjs} +20 -13
- package/dist/{hub-mdns-ciao-Bkrvgnma.js → hub-mdns-ciao-DB1Y9agt.js} +20 -13
- package/dist/index.d.ts +3 -4
- package/dist/index.js +145 -24
- package/dist/index.mjs +138 -22
- package/dist/kernel/config-schema.d.ts +5 -0
- package/dist/kernel/moleculer/accessory-prune-gate.d.ts +55 -0
- package/dist/log-file-read-protocol-B7M3X3bT.mjs +785 -0
- package/dist/log-file-read-protocol-D0WcLbIV.js +817 -0
- package/dist/log-file-read-worker.js +64 -0
- package/dist/log-file-read-worker.mjs +64 -0
- package/dist/log-read-filter-Bi066jwU.js +134 -0
- package/dist/log-read-filter-D7Ev3zm-.mjs +93 -0
- package/dist/logging/log-manager.d.ts +10 -6
- package/dist/logging/log-read-filter.d.ts +43 -0
- package/dist/{phase6-declare-gate-DrmTtz7F.js → phase6-declare-gate-BO-_jLh_.js} +1 -1
- package/dist/{phase6-declare-gate-JQUqgQgq.mjs → phase6-declare-gate-x9ZCbQJP.mjs} +1 -1
- package/dist/{restore-archive-4OP0EYg6.js → restore-archive-4DOUR5Gu.js} +1 -1
- package/dist/{restore-archive-YFSJRtKy.mjs → restore-archive-DyOaPeAr.mjs} +1 -1
- package/dist/tls/cert-issue.d.ts +16 -1
- package/dist/tls/cert-manager.d.ts +6 -0
- package/dist/tls/index.d.ts +1 -1
- package/dist/{wal-maintenance-TyuOEVy1.mjs → wal-maintenance-BMiX6UIa.mjs} +0 -0
- package/dist/{wal-maintenance-Bl0ZKjVR.js → wal-maintenance-DVN-DiVP.js} +0 -0
- package/package.json +1 -1
- package/dist/auth/admin-token-manager.d.ts +0 -51
- package/dist/auth/scoped-token-manager.d.ts +0 -25
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require("./chunk-Cek0wNdY.js");
|
|
2
|
+
const require_log_file_read_protocol = require("./log-file-read-protocol-D0WcLbIV.js");
|
|
3
|
+
let node_worker_threads = require("node:worker_threads");
|
|
4
|
+
//#region src/builtins/winston-logging/log-file-read-worker.ts
|
|
5
|
+
/**
|
|
6
|
+
* The rotated-file reader thread (D898) — a worker of whichever process runs
|
|
7
|
+
* `winston-logging`, so scanning and indexing a day of logs never runs on that
|
|
8
|
+
* process's event loop.
|
|
9
|
+
*
|
|
10
|
+
* A separate bundle (`dist/log-file-read-worker.js`, wired in
|
|
11
|
+
* `vite.config.ts`). It imports nothing from the kernel: the index, the
|
|
12
|
+
* reader and the shared line filter.
|
|
13
|
+
*/
|
|
14
|
+
function isWorkerData(value) {
|
|
15
|
+
return typeof value === "object" && value !== null && "logsDir" in value && typeof value.logsDir === "string" && "backgroundPassMs" in value && typeof value.backgroundPassMs === "number";
|
|
16
|
+
}
|
|
17
|
+
var port = node_worker_threads.parentPort;
|
|
18
|
+
if (port === null || !isWorkerData(node_worker_threads.workerData)) throw new Error("log-file-read-worker: started without a parent port or worker data");
|
|
19
|
+
var data = node_worker_threads.workerData;
|
|
20
|
+
var store = new require_log_file_read_protocol.LogFileIndexStore(data.logsDir);
|
|
21
|
+
var cancels = new require_log_file_read_protocol.CancelBook();
|
|
22
|
+
var stopping = false;
|
|
23
|
+
var passRunning = false;
|
|
24
|
+
async function backgroundPass() {
|
|
25
|
+
if (passRunning || stopping) return;
|
|
26
|
+
passRunning = true;
|
|
27
|
+
try {
|
|
28
|
+
await store.backgroundPass(() => stopping);
|
|
29
|
+
} catch {} finally {
|
|
30
|
+
passRunning = false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
var timer = data.backgroundPassMs > 0 ? setInterval(() => void backgroundPass(), data.backgroundPassMs) : null;
|
|
34
|
+
if (data.backgroundPassMs > 0) backgroundPass();
|
|
35
|
+
port.on("message", (message) => {
|
|
36
|
+
if (!require_log_file_read_protocol.isToReader(message)) return;
|
|
37
|
+
if (message.type === "stop") {
|
|
38
|
+
stopping = true;
|
|
39
|
+
if (timer !== null) clearInterval(timer);
|
|
40
|
+
port.close();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (message.type === "cancel") {
|
|
44
|
+
cancels.cancel(message.requestId);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const { id, query } = message;
|
|
48
|
+
require_log_file_read_protocol.serveRead(data.logsDir, store, cancels, query).then((outcome) => {
|
|
49
|
+
const reply = {
|
|
50
|
+
type: "result",
|
|
51
|
+
id,
|
|
52
|
+
result: outcome.result
|
|
53
|
+
};
|
|
54
|
+
port.postMessage(reply);
|
|
55
|
+
}, (error) => {
|
|
56
|
+
const reply = {
|
|
57
|
+
type: "error",
|
|
58
|
+
id,
|
|
59
|
+
message: error instanceof Error ? error.message : String(error)
|
|
60
|
+
};
|
|
61
|
+
port.postMessage(reply);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//#endregion
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { a as LogFileIndexStore, i as serveRead, r as isToReader, t as CancelBook } from "./log-file-read-protocol-B7M3X3bT.mjs";
|
|
2
|
+
import { parentPort, workerData } from "node:worker_threads";
|
|
3
|
+
//#region src/builtins/winston-logging/log-file-read-worker.ts
|
|
4
|
+
/**
|
|
5
|
+
* The rotated-file reader thread (D898) — a worker of whichever process runs
|
|
6
|
+
* `winston-logging`, so scanning and indexing a day of logs never runs on that
|
|
7
|
+
* process's event loop.
|
|
8
|
+
*
|
|
9
|
+
* A separate bundle (`dist/log-file-read-worker.js`, wired in
|
|
10
|
+
* `vite.config.ts`). It imports nothing from the kernel: the index, the
|
|
11
|
+
* reader and the shared line filter.
|
|
12
|
+
*/
|
|
13
|
+
function isWorkerData(value) {
|
|
14
|
+
return typeof value === "object" && value !== null && "logsDir" in value && typeof value.logsDir === "string" && "backgroundPassMs" in value && typeof value.backgroundPassMs === "number";
|
|
15
|
+
}
|
|
16
|
+
var port = parentPort;
|
|
17
|
+
if (port === null || !isWorkerData(workerData)) throw new Error("log-file-read-worker: started without a parent port or worker data");
|
|
18
|
+
var data = workerData;
|
|
19
|
+
var store = new LogFileIndexStore(data.logsDir);
|
|
20
|
+
var cancels = new CancelBook();
|
|
21
|
+
var stopping = false;
|
|
22
|
+
var passRunning = false;
|
|
23
|
+
async function backgroundPass() {
|
|
24
|
+
if (passRunning || stopping) return;
|
|
25
|
+
passRunning = true;
|
|
26
|
+
try {
|
|
27
|
+
await store.backgroundPass(() => stopping);
|
|
28
|
+
} catch {} finally {
|
|
29
|
+
passRunning = false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
var timer = data.backgroundPassMs > 0 ? setInterval(() => void backgroundPass(), data.backgroundPassMs) : null;
|
|
33
|
+
if (data.backgroundPassMs > 0) backgroundPass();
|
|
34
|
+
port.on("message", (message) => {
|
|
35
|
+
if (!isToReader(message)) return;
|
|
36
|
+
if (message.type === "stop") {
|
|
37
|
+
stopping = true;
|
|
38
|
+
if (timer !== null) clearInterval(timer);
|
|
39
|
+
port.close();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (message.type === "cancel") {
|
|
43
|
+
cancels.cancel(message.requestId);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { id, query } = message;
|
|
47
|
+
serveRead(data.logsDir, store, cancels, query).then((outcome) => {
|
|
48
|
+
const reply = {
|
|
49
|
+
type: "result",
|
|
50
|
+
id,
|
|
51
|
+
result: outcome.result
|
|
52
|
+
};
|
|
53
|
+
port.postMessage(reply);
|
|
54
|
+
}, (error) => {
|
|
55
|
+
const reply = {
|
|
56
|
+
type: "error",
|
|
57
|
+
id,
|
|
58
|
+
message: error instanceof Error ? error.message : String(error)
|
|
59
|
+
};
|
|
60
|
+
port.postMessage(reply);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//#endregion
|
|
64
|
+
export {};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
//#region src/logging/log-read-filter.ts
|
|
2
|
+
var LEVEL_RANK = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3
|
|
7
|
+
};
|
|
8
|
+
function levelRank(level) {
|
|
9
|
+
return level === "debug" || level === "info" || level === "warn" || level === "error" ? LEVEL_RANK[level] : LEVEL_RANK.info;
|
|
10
|
+
}
|
|
11
|
+
/** `provider@1.2.3` / `audio-codec::native-device-ops` → the manifest id. */
|
|
12
|
+
function bareAddonOf(raw) {
|
|
13
|
+
if (typeof raw !== "string" || raw.length === 0) return null;
|
|
14
|
+
let bare = raw.split("@")[0] ?? raw;
|
|
15
|
+
const colon = bare.indexOf("::");
|
|
16
|
+
if (colon >= 0) bare = bare.slice(0, colon);
|
|
17
|
+
return bare;
|
|
18
|
+
}
|
|
19
|
+
/** The node a line is attributed to for the `nodeId` filter and the block index. */
|
|
20
|
+
function originNodeOf(tags) {
|
|
21
|
+
const agentId = tags?.["agentId"];
|
|
22
|
+
if (typeof agentId === "string" && agentId.length > 0) return agentId;
|
|
23
|
+
const nodeId = tags?.["nodeId"];
|
|
24
|
+
if (typeof nodeId === "string" && nodeId.length > 0) {
|
|
25
|
+
const slash = nodeId.indexOf("/");
|
|
26
|
+
return slash === -1 ? nodeId : nodeId.slice(0, slash);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function nodeMatches(tags, want) {
|
|
31
|
+
if (tags === void 0) return false;
|
|
32
|
+
const agentId = tags["agentId"];
|
|
33
|
+
const nodeId = tags["nodeId"];
|
|
34
|
+
if (agentId === want || nodeId === want) return true;
|
|
35
|
+
return typeof nodeId === "string" && nodeId.startsWith(`${want}/`);
|
|
36
|
+
}
|
|
37
|
+
function stringifyValue(value) {
|
|
38
|
+
if (typeof value === "string") return value;
|
|
39
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
40
|
+
try {
|
|
41
|
+
return JSON.stringify(value) ?? "";
|
|
42
|
+
} catch {
|
|
43
|
+
return String(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Case-insensitive substring over message, scope, every tag value and every meta value. */
|
|
47
|
+
function lineContainsText(line, needleLower) {
|
|
48
|
+
if (line.message.toLowerCase().includes(needleLower)) return true;
|
|
49
|
+
if (line.scope !== void 0 && line.scope.toLowerCase().includes(needleLower)) return true;
|
|
50
|
+
for (const bag of [line.tags, line.meta]) {
|
|
51
|
+
if (bag === void 0) continue;
|
|
52
|
+
for (const value of Object.values(bag)) {
|
|
53
|
+
if (value === void 0 || value === null) continue;
|
|
54
|
+
if (stringifyValue(value).toLowerCase().includes(needleLower)) return true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
function compileLogFilter(query) {
|
|
60
|
+
const text = query.text?.trim() ?? "";
|
|
61
|
+
return {
|
|
62
|
+
deviceId: query.deviceId ?? null,
|
|
63
|
+
addonId: query.fromAddonId !== void 0 ? bareAddonOf(query.fromAddonId) : null,
|
|
64
|
+
nodeId: query.fromNodeId ?? null,
|
|
65
|
+
tags: query.tags ?? {},
|
|
66
|
+
levelFloor: query.level !== void 0 ? LEVEL_RANK[query.level] : 0,
|
|
67
|
+
textLower: text.length > 0 ? text.toLowerCase() : null,
|
|
68
|
+
since: query.since ?? null,
|
|
69
|
+
until: query.until ?? null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** Exact match of one line against the whole filter. */
|
|
73
|
+
function lineMatches(line, filter) {
|
|
74
|
+
if (levelRank(line.level) < filter.levelFloor) return false;
|
|
75
|
+
if (filter.since !== null && line.timestamp < filter.since) return false;
|
|
76
|
+
if (filter.until !== null && line.timestamp > filter.until) return false;
|
|
77
|
+
const tags = line.tags;
|
|
78
|
+
if (filter.deviceId !== null && tags?.["deviceId"] !== filter.deviceId) return false;
|
|
79
|
+
if (filter.addonId !== null && bareAddonOf(tags?.["addonId"]) !== filter.addonId) return false;
|
|
80
|
+
if (filter.nodeId !== null && !nodeMatches(tags, filter.nodeId)) return false;
|
|
81
|
+
for (const [key, want] of Object.entries(filter.tags)) {
|
|
82
|
+
const have = tags?.[key];
|
|
83
|
+
if (have !== want && !(typeof have === "number" && String(have) === String(want))) return false;
|
|
84
|
+
}
|
|
85
|
+
if (filter.textLower !== null && !lineContainsText(line, filter.textLower)) return false;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/** True when the filter constrains nothing — every line matches. */
|
|
89
|
+
function filterIsEmpty(filter) {
|
|
90
|
+
return filter.deviceId === null && filter.addonId === null && filter.nodeId === null && Object.keys(filter.tags).length === 0 && filter.levelFloor === 0 && filter.textLower === null && filter.since === null && filter.until === null;
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
Object.defineProperty(exports, "bareAddonOf", {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
get: function() {
|
|
96
|
+
return bareAddonOf;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
Object.defineProperty(exports, "compileLogFilter", {
|
|
100
|
+
enumerable: true,
|
|
101
|
+
get: function() {
|
|
102
|
+
return compileLogFilter;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
Object.defineProperty(exports, "filterIsEmpty", {
|
|
106
|
+
enumerable: true,
|
|
107
|
+
get: function() {
|
|
108
|
+
return filterIsEmpty;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
Object.defineProperty(exports, "levelRank", {
|
|
112
|
+
enumerable: true,
|
|
113
|
+
get: function() {
|
|
114
|
+
return levelRank;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
Object.defineProperty(exports, "lineContainsText", {
|
|
118
|
+
enumerable: true,
|
|
119
|
+
get: function() {
|
|
120
|
+
return lineContainsText;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
Object.defineProperty(exports, "lineMatches", {
|
|
124
|
+
enumerable: true,
|
|
125
|
+
get: function() {
|
|
126
|
+
return lineMatches;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
Object.defineProperty(exports, "originNodeOf", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
get: function() {
|
|
132
|
+
return originNodeOf;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//#region src/logging/log-read-filter.ts
|
|
2
|
+
var LEVEL_RANK = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3
|
|
7
|
+
};
|
|
8
|
+
function levelRank(level) {
|
|
9
|
+
return level === "debug" || level === "info" || level === "warn" || level === "error" ? LEVEL_RANK[level] : LEVEL_RANK.info;
|
|
10
|
+
}
|
|
11
|
+
/** `provider@1.2.3` / `audio-codec::native-device-ops` → the manifest id. */
|
|
12
|
+
function bareAddonOf(raw) {
|
|
13
|
+
if (typeof raw !== "string" || raw.length === 0) return null;
|
|
14
|
+
let bare = raw.split("@")[0] ?? raw;
|
|
15
|
+
const colon = bare.indexOf("::");
|
|
16
|
+
if (colon >= 0) bare = bare.slice(0, colon);
|
|
17
|
+
return bare;
|
|
18
|
+
}
|
|
19
|
+
/** The node a line is attributed to for the `nodeId` filter and the block index. */
|
|
20
|
+
function originNodeOf(tags) {
|
|
21
|
+
const agentId = tags?.["agentId"];
|
|
22
|
+
if (typeof agentId === "string" && agentId.length > 0) return agentId;
|
|
23
|
+
const nodeId = tags?.["nodeId"];
|
|
24
|
+
if (typeof nodeId === "string" && nodeId.length > 0) {
|
|
25
|
+
const slash = nodeId.indexOf("/");
|
|
26
|
+
return slash === -1 ? nodeId : nodeId.slice(0, slash);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function nodeMatches(tags, want) {
|
|
31
|
+
if (tags === void 0) return false;
|
|
32
|
+
const agentId = tags["agentId"];
|
|
33
|
+
const nodeId = tags["nodeId"];
|
|
34
|
+
if (agentId === want || nodeId === want) return true;
|
|
35
|
+
return typeof nodeId === "string" && nodeId.startsWith(`${want}/`);
|
|
36
|
+
}
|
|
37
|
+
function stringifyValue(value) {
|
|
38
|
+
if (typeof value === "string") return value;
|
|
39
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
40
|
+
try {
|
|
41
|
+
return JSON.stringify(value) ?? "";
|
|
42
|
+
} catch {
|
|
43
|
+
return String(value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Case-insensitive substring over message, scope, every tag value and every meta value. */
|
|
47
|
+
function lineContainsText(line, needleLower) {
|
|
48
|
+
if (line.message.toLowerCase().includes(needleLower)) return true;
|
|
49
|
+
if (line.scope !== void 0 && line.scope.toLowerCase().includes(needleLower)) return true;
|
|
50
|
+
for (const bag of [line.tags, line.meta]) {
|
|
51
|
+
if (bag === void 0) continue;
|
|
52
|
+
for (const value of Object.values(bag)) {
|
|
53
|
+
if (value === void 0 || value === null) continue;
|
|
54
|
+
if (stringifyValue(value).toLowerCase().includes(needleLower)) return true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
function compileLogFilter(query) {
|
|
60
|
+
const text = query.text?.trim() ?? "";
|
|
61
|
+
return {
|
|
62
|
+
deviceId: query.deviceId ?? null,
|
|
63
|
+
addonId: query.fromAddonId !== void 0 ? bareAddonOf(query.fromAddonId) : null,
|
|
64
|
+
nodeId: query.fromNodeId ?? null,
|
|
65
|
+
tags: query.tags ?? {},
|
|
66
|
+
levelFloor: query.level !== void 0 ? LEVEL_RANK[query.level] : 0,
|
|
67
|
+
textLower: text.length > 0 ? text.toLowerCase() : null,
|
|
68
|
+
since: query.since ?? null,
|
|
69
|
+
until: query.until ?? null
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** Exact match of one line against the whole filter. */
|
|
73
|
+
function lineMatches(line, filter) {
|
|
74
|
+
if (levelRank(line.level) < filter.levelFloor) return false;
|
|
75
|
+
if (filter.since !== null && line.timestamp < filter.since) return false;
|
|
76
|
+
if (filter.until !== null && line.timestamp > filter.until) return false;
|
|
77
|
+
const tags = line.tags;
|
|
78
|
+
if (filter.deviceId !== null && tags?.["deviceId"] !== filter.deviceId) return false;
|
|
79
|
+
if (filter.addonId !== null && bareAddonOf(tags?.["addonId"]) !== filter.addonId) return false;
|
|
80
|
+
if (filter.nodeId !== null && !nodeMatches(tags, filter.nodeId)) return false;
|
|
81
|
+
for (const [key, want] of Object.entries(filter.tags)) {
|
|
82
|
+
const have = tags?.[key];
|
|
83
|
+
if (have !== want && !(typeof have === "number" && String(have) === String(want))) return false;
|
|
84
|
+
}
|
|
85
|
+
if (filter.textLower !== null && !lineContainsText(line, filter.textLower)) return false;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
/** True when the filter constrains nothing — every line matches. */
|
|
89
|
+
function filterIsEmpty(filter) {
|
|
90
|
+
return filter.deviceId === null && filter.addonId === null && filter.nodeId === null && Object.keys(filter.tags).length === 0 && filter.levelFloor === 0 && filter.textLower === null && filter.since === null && filter.until === null;
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { lineContainsText as a, levelRank as i, compileLogFilter as n, lineMatches as o, filterIsEmpty as r, originNodeOf as s, bareAddonOf as t };
|
|
@@ -2,12 +2,8 @@ import { type LogEntry, type LogFilter, type LogLevel } from "./log-ring-buffer.
|
|
|
2
2
|
import type { LoggingGate } from "./logging-gate.js";
|
|
3
3
|
import { type PartitionedLogBufferOptions } from "./partitioned-log-buffer.js";
|
|
4
4
|
import { type IScopedLogger } from "./scoped-logger.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
shutdown(): Promise<void>;
|
|
8
|
-
write(entry: LogEntry): void;
|
|
9
|
-
query?(filter: LogFilter): Promise<readonly LogEntry[]>;
|
|
10
|
-
}
|
|
5
|
+
import type { ILogDestination } from "@camstack/types";
|
|
6
|
+
export type { ILogDestination };
|
|
11
7
|
/**
|
|
12
8
|
* The reserved destination id of the in-memory buffer. Not an addon: the
|
|
13
9
|
* buffer must exist before any addon loads (boot lines) and it backs
|
|
@@ -62,6 +58,14 @@ export declare class LogManager {
|
|
|
62
58
|
*/
|
|
63
59
|
private gate;
|
|
64
60
|
/**
|
|
61
|
+
* Entry identity (D898): `<bootId>.<seq>`, stamped once, here, on every line
|
|
62
|
+
* this process accepts — so the in-memory tail, the live subscription and
|
|
63
|
+
* the rotated file carry the SAME id and a page read from disk dedupes
|
|
64
|
+
* exactly against the lines pushed live.
|
|
65
|
+
*/
|
|
66
|
+
private readonly bootId;
|
|
67
|
+
private seq;
|
|
68
|
+
/**
|
|
65
69
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
66
70
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
67
71
|
*
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE definition of "does this line match a history read" (D898).
|
|
3
|
+
*
|
|
4
|
+
* Used by every reader — the rotated-file reader in its worker, the Loki
|
|
5
|
+
* reader after LogQL has narrowed the stream, and the hub's in-memory tail —
|
|
6
|
+
* so the same query cannot mean three different things on three sources.
|
|
7
|
+
*
|
|
8
|
+
* It is deliberately free of value imports: the file reader runs it inside a
|
|
9
|
+
* bare worker thread.
|
|
10
|
+
*/
|
|
11
|
+
import type { LogReadQuery } from "@camstack/types";
|
|
12
|
+
/** A structurally-typed line: a parsed file row, a ring entry or a Loki line. */
|
|
13
|
+
export interface ReadableLine {
|
|
14
|
+
readonly timestamp: number;
|
|
15
|
+
readonly level: string;
|
|
16
|
+
readonly message: string;
|
|
17
|
+
readonly scope?: string | undefined;
|
|
18
|
+
readonly tags?: Readonly<Record<string, unknown>> | undefined;
|
|
19
|
+
readonly meta?: Readonly<Record<string, unknown>> | undefined;
|
|
20
|
+
}
|
|
21
|
+
export declare function levelRank(level: string): number;
|
|
22
|
+
/** `provider@1.2.3` / `audio-codec::native-device-ops` → the manifest id. */
|
|
23
|
+
export declare function bareAddonOf(raw: unknown): string | null;
|
|
24
|
+
/** The node a line is attributed to for the `nodeId` filter and the block index. */
|
|
25
|
+
export declare function originNodeOf(tags: Readonly<Record<string, unknown>> | undefined): string | null;
|
|
26
|
+
/** Case-insensitive substring over message, scope, every tag value and every meta value. */
|
|
27
|
+
export declare function lineContainsText(line: ReadableLine, needleLower: string): boolean;
|
|
28
|
+
/** The filter half of a {@link LogReadQuery}, normalised once per read. */
|
|
29
|
+
export interface CompiledLogFilter {
|
|
30
|
+
readonly deviceId: number | null;
|
|
31
|
+
readonly addonId: string | null;
|
|
32
|
+
readonly nodeId: string | null;
|
|
33
|
+
readonly tags: Readonly<Record<string, string | number>>;
|
|
34
|
+
readonly levelFloor: number;
|
|
35
|
+
readonly textLower: string | null;
|
|
36
|
+
readonly since: number | null;
|
|
37
|
+
readonly until: number | null;
|
|
38
|
+
}
|
|
39
|
+
export declare function compileLogFilter(query: LogReadQuery): CompiledLogFilter;
|
|
40
|
+
/** Exact match of one line against the whole filter. */
|
|
41
|
+
export declare function lineMatches(line: ReadableLine, filter: CompiledLogFilter): boolean;
|
|
42
|
+
/** True when the filter constrains nothing — every line matches. */
|
|
43
|
+
export declare function filterIsEmpty(filter: CompiledLogFilter): boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_dist = require("./dist-
|
|
1
|
+
const require_dist = require("./dist-C89nqNnn.js");
|
|
2
2
|
//#region src/builtins/records/legacy-table-row-count.ts
|
|
3
3
|
/** Row count for a physical settings-db table (matches the records engine `legacyRowCount`). */
|
|
4
4
|
function legacyTableRowCountFromList(tables, collection) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Wi as declarationsOf } from "./dist-Dhux90yB.mjs";
|
|
2
2
|
//#region src/builtins/records/legacy-table-row-count.ts
|
|
3
3
|
/** Row count for a physical settings-db table (matches the records engine `legacyRowCount`). */
|
|
4
4
|
function legacyTableRowCountFromList(tables, collection) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-C89nqNnn.js");
|
|
3
3
|
const require_read_all_rows$1 = require("./read-all-rows-CVoO1ONM.js");
|
|
4
4
|
let zod = require("zod");
|
|
5
5
|
let node_crypto = require("node:crypto");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ki as defineRecordKinds, N as DataStoreDatabaseSchema, S as DATABASE_SNAPSHOT_SUFFIX } from "./dist-Dhux90yB.mjs";
|
|
2
2
|
import { t as require_read_all_rows } from "./read-all-rows-TaPqdWNF.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createPublicKey, diffieHellman, generateKeyPairSync, hkdfSync, randomBytes } from "node:crypto";
|
package/dist/tls/cert-issue.d.ts
CHANGED
|
@@ -3,6 +3,19 @@ import { X509Certificate as PeculiarCertificate } from "@peculiar/x509";
|
|
|
3
3
|
import type { CertIdentity } from "./cert-identity.js";
|
|
4
4
|
/** Subject of the local root. Distinct from the leaf's CN by construction. */
|
|
5
5
|
export declare const CA_COMMON_NAME = "CamStack Local CA";
|
|
6
|
+
/** Between {@link CA_COMMON_NAME} and the hub's name in a new root's subject. */
|
|
7
|
+
export declare const CA_HUB_NAME_SEPARATOR = " — ";
|
|
8
|
+
/**
|
|
9
|
+
* The subject CN of a NEW local root: `CamStack Local CA — <hub name>`, so two hubs'
|
|
10
|
+
* roots installed on one phone can be told apart in its settings. The name is
|
|
11
|
+
* sanitised for a CN (controls removed, whitespace collapsed) and cut so the whole
|
|
12
|
+
* CN stays within 64 characters. An absent or unusable name, or one that is just
|
|
13
|
+
* the product's own name, yields the plain {@link CA_COMMON_NAME}.
|
|
14
|
+
*
|
|
15
|
+
* Only a root being CREATED is named: an existing root is never reissued to rename
|
|
16
|
+
* it, since every device that trusts it would have to install it again.
|
|
17
|
+
*/
|
|
18
|
+
export declare function localCaCommonName(hubName: string | undefined): string;
|
|
6
19
|
/** A PEM-encoded certificate and the PKCS#8 PEM of its private key. */
|
|
7
20
|
export interface CertMaterial {
|
|
8
21
|
readonly certPem: string;
|
|
@@ -23,8 +36,10 @@ export interface CaSigner {
|
|
|
23
36
|
* It carries a CRITICAL `nameConstraints` extension (D873): private address
|
|
24
37
|
* ranges and local-only DNS names, plus `hostnames` (the hub's own single-label
|
|
25
38
|
* names at creation). A leaked key therefore cannot vouch for a public site.
|
|
39
|
+
*
|
|
40
|
+
* `commonName` is the subject CN, from {@link localCaCommonName}.
|
|
26
41
|
*/
|
|
27
|
-
export declare function generateCa(now: Date, hostnames?: readonly string[]): Promise<CaSigner>;
|
|
42
|
+
export declare function generateCa(now: Date, hostnames?: readonly string[], commonName?: string): Promise<CaSigner>;
|
|
28
43
|
/** Re-open a root already on disk so a leaf can be issued under it. */
|
|
29
44
|
export declare function loadCa(certPem: string, keyPem: string): Promise<CaSigner>;
|
|
30
45
|
/**
|
|
@@ -41,6 +41,12 @@ export interface EnsureTlsResult {
|
|
|
41
41
|
export interface CertOptions {
|
|
42
42
|
/** Common Name for the leaf (default: 'camstack.local') */
|
|
43
43
|
readonly commonName?: string;
|
|
44
|
+
/**
|
|
45
|
+
* The hub's human name (D861). Read only when a NEW local root is created: its subject
|
|
46
|
+
* becomes `CamStack Local CA — <hubName>` ({@link localCaCommonName}). An existing root
|
|
47
|
+
* is never reissued because this changed. Absent: the plain `CamStack Local CA`.
|
|
48
|
+
*/
|
|
49
|
+
readonly hubName?: string;
|
|
44
50
|
/** Leaf validity in days. Clamped to `MAX_LEAF_VALIDITY_DAYS`. */
|
|
45
51
|
readonly validDays?: number;
|
|
46
52
|
/** Additional SANs (DNS names or IPs). Required coverage by definition. */
|
package/dist/tls/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { type CertIdentity, type CertOptions, type HostFacts, type CertRegenerat
|
|
|
3
3
|
export { type BootTls, type BootTlsMode, prepareBootTls } from "./boot-tls.js";
|
|
4
4
|
export { clearHttpsListener, type HttpsReloadOutcome, leafFingerprintOf, registerHttpsListener, reloadHttpsListener, servedHttpsLeafFingerprint } from "./https-listener.js";
|
|
5
5
|
export { applyCertificateToListener, regenerateCertificate, revertToGeneratedCertificate, storeUploadedCertificate, type UploadCertificateInput, useStoredUploadedCertificate } from "./tls-actions.js";
|
|
6
|
-
export { CA_COMMON_NAME } from "./cert-issue.js";
|
|
6
|
+
export { CA_COMMON_NAME, localCaCommonName } from "./cert-issue.js";
|
|
7
7
|
export { checkUploadedCa, chainsToPublicRoot, validateUploadedTls, type UploadedCaCheck, type UploadedTlsErrorCode, type UploadedTlsValidation } from "./uploaded-cert.js";
|
|
8
8
|
export { buildNameConstraintSet, isConstrainedCa, type NameConstraintSet, permitsIdentity, permitsName, readNameConstraints, PERMITTED_DNS_SUFFIXES, PERMITTED_IP_RANGES } from "./cert-name-constraints.js";
|
|
9
9
|
export { type StoredUploadInfo, type TlsAccessStatus, readTlsAccessStatus, splitPemCertificates, UPLOADED_CA_FILE, writeTlsMode, readTlsMode, readExtraSans, writeExtraSans } from "./tls-status.js";
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { CollectionColumn, RecordKindHandle, SettingsStoreClient } from "@camstack/types";
|
|
2
|
-
import type { AdminTokenBody } from "../builtins/local-auth/record-kinds.js";
|
|
3
|
-
/**
|
|
4
|
-
* @durable class=config owner=local-auth
|
|
5
|
-
* write="an admin creates a token (after re-authentication); `lastUsedAt` is
|
|
6
|
-
* rewritten at most once a minute while it is used; `revoke` stamps revokedAt"
|
|
7
|
-
* retention="the daily reap deletes rows expired or revoked more than 30 days ago"
|
|
8
|
-
*/
|
|
9
|
-
export declare const ADMIN_TOKENS_COLLECTION = "admin_tokens";
|
|
10
|
-
export declare const ADMIN_TOKENS_COLUMNS: readonly CollectionColumn[];
|
|
11
|
-
export declare const ADMIN_TOKEN_PREFIX = "csa_";
|
|
12
|
-
export declare const ADMIN_TOKEN_MAX_LIFETIME_MS: number;
|
|
13
|
-
export interface AdminTokenRecord {
|
|
14
|
-
readonly id: string;
|
|
15
|
-
readonly createdBy: string;
|
|
16
|
-
readonly name: string;
|
|
17
|
-
readonly tokenPrefix: string;
|
|
18
|
-
readonly createdAt: number;
|
|
19
|
-
readonly expiresAt: number;
|
|
20
|
-
readonly lastUsedAt: number | null;
|
|
21
|
-
readonly revokedAt: number | null;
|
|
22
|
-
}
|
|
23
|
-
export interface AdminTokenRecordsDeps {
|
|
24
|
-
readonly adminTokensKind: RecordKindHandle<AdminTokenBody>;
|
|
25
|
-
readonly store?: SettingsStoreClient;
|
|
26
|
-
}
|
|
27
|
-
export declare class AdminTokenManager {
|
|
28
|
-
private readonly now;
|
|
29
|
-
private readonly kind;
|
|
30
|
-
private readonly store;
|
|
31
|
-
constructor(deps: SettingsStoreClient | AdminTokenRecordsDeps, now?: () => number);
|
|
32
|
-
/** Mint a token for `createdBy`. Refuses an expiry in the past or past 90 days. */
|
|
33
|
-
create(input: {
|
|
34
|
-
readonly createdBy: string;
|
|
35
|
-
readonly name: string;
|
|
36
|
-
readonly expiresAt: number;
|
|
37
|
-
}): Promise<{
|
|
38
|
-
readonly token: string;
|
|
39
|
-
readonly record: AdminTokenRecord;
|
|
40
|
-
}>;
|
|
41
|
-
/** The live record behind `token`, or `null` (unknown, revoked, expired, not a `csa_`). */
|
|
42
|
-
validate(token: string): Promise<AdminTokenRecord | null>;
|
|
43
|
-
/** Every token not yet reaped, newest first (no hashes). */
|
|
44
|
-
list(): Promise<readonly AdminTokenRecord[]>;
|
|
45
|
-
/** Revoke one token. `false` when unknown or already revoked. */
|
|
46
|
-
revoke(id: string): Promise<boolean>;
|
|
47
|
-
/** Revoke every live token `userId` created (the user was deleted). */
|
|
48
|
-
revokeAllCreatedBy(userId: string): Promise<number>;
|
|
49
|
-
/** Delete rows expired or revoked more than 30 days ago. */
|
|
50
|
-
reap(): Promise<number>;
|
|
51
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { RecordKindHandle, ScopedToken, TokenScope, SettingsStoreClient } from "@camstack/types";
|
|
2
|
-
import type { ScopedTokenBody } from "../builtins/local-auth/record-kinds.js";
|
|
3
|
-
export interface ScopedTokenRecordsDeps {
|
|
4
|
-
readonly scopedTokensKind: RecordKindHandle<ScopedTokenBody>;
|
|
5
|
-
readonly legacyStore?: SettingsStoreClient;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Manages scoped API tokens with restricted addon/route/capability access.
|
|
9
|
-
*/
|
|
10
|
-
export declare class ScopedTokenManager {
|
|
11
|
-
private readonly kind;
|
|
12
|
-
private readonly store;
|
|
13
|
-
constructor(deps: SettingsStoreClient | ScopedTokenRecordsDeps);
|
|
14
|
-
create(userId: string, name: string, scopes: TokenScope[], expiresAt?: number): Promise<{
|
|
15
|
-
token: string;
|
|
16
|
-
record: ScopedToken;
|
|
17
|
-
}>;
|
|
18
|
-
validate(rawToken: string): Promise<ScopedToken | null>;
|
|
19
|
-
matchesScope(token: ScopedToken, addonId?: string, capability?: string): boolean;
|
|
20
|
-
revoke(tokenId: string): Promise<boolean>;
|
|
21
|
-
listForUser(userId: string): Promise<ScopedToken[]>;
|
|
22
|
-
updateLastUsed(tokenId: string): Promise<void>;
|
|
23
|
-
reapExpired(nowMs?: number): Promise<number>;
|
|
24
|
-
cleanupOrphans(validUserIds: ReadonlySet<string>): Promise<number>;
|
|
25
|
-
}
|