@uns-kit/core 3.0.25 → 3.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/MIGRATIONS.md +51 -0
  2. package/dist/runtime/compatibility/energenti-authorization-v1.d.ts +95 -0
  3. package/dist/runtime/compatibility/energenti-authorization-v1.d.ts.map +1 -0
  4. package/dist/runtime/compatibility/energenti-authorization-v1.js +315 -0
  5. package/dist/runtime/compatibility/energenti-authorization-v1.js.map +1 -0
  6. package/dist/runtime/compatibility/energenti-descriptor-v1.d.ts +10 -0
  7. package/dist/runtime/compatibility/energenti-descriptor-v1.d.ts.map +1 -0
  8. package/dist/runtime/compatibility/energenti-descriptor-v1.js +18 -0
  9. package/dist/runtime/compatibility/energenti-descriptor-v1.js.map +1 -0
  10. package/dist/runtime/process-group-authorization.d.ts +107 -0
  11. package/dist/runtime/process-group-authorization.d.ts.map +1 -0
  12. package/dist/runtime/process-group-authorization.js +352 -0
  13. package/dist/runtime/process-group-authorization.js.map +1 -0
  14. package/dist/runtime/process-group-contract.d.ts +65 -0
  15. package/dist/runtime/process-group-contract.d.ts.map +1 -0
  16. package/dist/runtime/process-group-contract.js +171 -0
  17. package/dist/runtime/process-group-contract.js.map +1 -0
  18. package/dist/runtime/process-group-control-contract.d.ts +56 -0
  19. package/dist/runtime/process-group-control-contract.d.ts.map +1 -0
  20. package/dist/runtime/process-group-control-contract.js +37 -0
  21. package/dist/runtime/process-group-control-contract.js.map +1 -0
  22. package/dist/runtime/process-group-inspection.d.ts +22 -0
  23. package/dist/runtime/process-group-inspection.d.ts.map +1 -0
  24. package/dist/runtime/process-group-inspection.js +185 -0
  25. package/dist/runtime/process-group-inspection.js.map +1 -0
  26. package/dist/runtime/process-group-launch-environment.d.ts +3 -0
  27. package/dist/runtime/process-group-launch-environment.d.ts.map +1 -0
  28. package/dist/runtime/process-group-launch-environment.js +12 -0
  29. package/dist/runtime/process-group-launch-environment.js.map +1 -0
  30. package/dist/runtime/process-group-legacy-start.d.ts +2 -0
  31. package/dist/runtime/process-group-legacy-start.d.ts.map +1 -0
  32. package/dist/runtime/process-group-legacy-start.js +16 -0
  33. package/dist/runtime/process-group-legacy-start.js.map +1 -0
  34. package/dist/runtime/process-group-resources.d.ts +8 -0
  35. package/dist/runtime/process-group-resources.d.ts.map +1 -0
  36. package/dist/runtime/process-group-resources.js +96 -0
  37. package/dist/runtime/process-group-resources.js.map +1 -0
  38. package/dist/runtime/process-group-snapshot.mjs +199 -0
  39. package/dist/runtime/process-group-staging.d.ts +5 -0
  40. package/dist/runtime/process-group-staging.d.ts.map +1 -0
  41. package/dist/runtime/process-group-staging.js +63 -0
  42. package/dist/runtime/process-group-staging.js.map +1 -0
  43. package/dist/runtime/process-group-supervision.d.ts +13 -0
  44. package/dist/runtime/process-group-supervision.d.ts.map +1 -0
  45. package/dist/runtime/process-group-supervision.js +34 -0
  46. package/dist/runtime/process-group-supervision.js.map +1 -0
  47. package/dist/uns/uns-attributes.d.ts +2 -2
  48. package/dist/uns-mqtt/mqtt-proxy.d.ts +3 -0
  49. package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
  50. package/dist/uns-mqtt/mqtt-proxy.js +38 -0
  51. package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
  52. package/dist/uns-mqtt/subscription-readiness.d.ts +23 -0
  53. package/dist/uns-mqtt/subscription-readiness.d.ts.map +1 -0
  54. package/dist/uns-mqtt/subscription-readiness.js +50 -0
  55. package/dist/uns-mqtt/subscription-readiness.js.map +1 -0
  56. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ /** Frozen source-API bridge for older callers; new launchers use installed descriptors. */
2
+ import { configuredGroupProcessNames } from "./process-group-authorization.js";
3
+ import { legacyEnergentiDescriptor, normalizeProcessGroupConfiguration } from "./process-group-contract.js";
4
+ export function assertLegacyDirectStartAllowed(raw, configured) {
5
+ const c = normalizeProcessGroupConfiguration(raw, legacyEnergentiDescriptor);
6
+ if (!c.matches || c.journal)
7
+ return;
8
+ const names = configured === undefined
9
+ ? configuredGroupProcessNames()
10
+ : configured
11
+ ? new Set(["uns-energenti-san", "uns-energenti-crno", "uns-energenti-kepware-hv", "uns-energenti-kepware-hv-admission"])
12
+ : new Set();
13
+ if (names.has(String(c.uns?.["processName"])))
14
+ throw Error("Group has a configured admission policy; direct-input originals cannot be started beside retained journal work");
15
+ }
16
+ //# sourceMappingURL=process-group-legacy-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-legacy-start.js","sourceRoot":"","sources":["../../src/runtime/process-group-legacy-start.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AAE5G,MAAM,UAAU,8BAA8B,CAAC,GAA4B,EAAE,UAAoB;IAC/F,MAAM,CAAC,GAAG,kCAAkC,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;IAC7E,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO;QAAE,OAAO;IACpC,MAAM,KAAK,GACT,UAAU,KAAK,SAAS;QACtB,CAAC,CAAC,2BAA2B,EAAE;QAC/B,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,mBAAmB,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,oCAAoC,CAAC,CAAC;YACxH,CAAC,CAAC,IAAI,GAAG,EAAU,CAAC;IAC1B,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;QAC3C,MAAM,KAAK,CAAC,gHAAgH,CAAC,CAAC;AAClI,CAAC","sourcesContent":["/** Frozen source-API bridge for older callers; new launchers use installed descriptors. */\nimport { configuredGroupProcessNames } from \"./process-group-authorization.js\";\nimport { legacyEnergentiDescriptor, normalizeProcessGroupConfiguration } from \"./process-group-contract.js\";\n\nexport function assertLegacyDirectStartAllowed(raw: Record<string, unknown>, configured?: boolean): void {\n const c = normalizeProcessGroupConfiguration(raw, legacyEnergentiDescriptor);\n if (!c.matches || c.journal) return;\n const names =\n configured === undefined\n ? configuredGroupProcessNames()\n : configured\n ? new Set([\"uns-energenti-san\", \"uns-energenti-crno\", \"uns-energenti-kepware-hv\", \"uns-energenti-kepware-hv-admission\"])\n : new Set<string>();\n if (names.has(String(c.uns?.[\"processName\"])))\n throw Error(\"Group has a configured admission policy; direct-input originals cannot be started beside retained journal work\");\n}\n"]}
@@ -0,0 +1,8 @@
1
+ export declare const sha256: (b: string | Buffer) => string;
2
+ export declare const configurationAuthorizationHash: (v: unknown) => string;
3
+ export declare function readProcessGroupResource(file: string, privateFile?: boolean): Buffer;
4
+ /** Pins metadata and compiled JS/JSON modules, not an installed dependency tree. */
5
+ export declare function groupArtifactHash(root: string): string;
6
+ /** Endpoint/TLS identity only; credentials never become a policy field or diagnostic. */
7
+ export declare function groupChannelsHash(channels: unknown[]): string;
8
+ //# sourceMappingURL=process-group-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-resources.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-resources.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,GAAG,MAAM,WAAiD,CAAC;AAW3F,eAAO,MAAM,8BAA8B,GAAI,GAAG,OAAO,KAAG,MAA8C,CAAC;AAC3G,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,MAAM,CAelF;AACD,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA+BtD;AACD,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAoB7D"}
@@ -0,0 +1,96 @@
1
+ import { createHash } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ export const sha256 = (b) => createHash("sha256").update(b).digest("hex");
5
+ function canonical(v) {
6
+ if (Array.isArray(v))
7
+ return v.map(canonical);
8
+ return v && typeof v === "object"
9
+ ? Object.fromEntries(Object.entries(v)
10
+ .sort(([a], [b]) => a.localeCompare(b))
11
+ .map(([k, x]) => [k, canonical(x)]))
12
+ : v;
13
+ }
14
+ export const configurationAuthorizationHash = (v) => sha256(JSON.stringify(canonical(v)));
15
+ export function readProcessGroupResource(file, privateFile = false) {
16
+ if (file.length > 512 || path.resolve(file) !== file)
17
+ throw Error("Process-group authorization resource path is not normalized");
18
+ for (let p = file; p !== path.dirname(p); p = path.dirname(p))
19
+ if (fs.lstatSync(p).isSymbolicLink())
20
+ throw Error("Process-group authorization resource cannot contain links");
21
+ const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
22
+ try {
23
+ const s = fs.fstatSync(fd);
24
+ if (!s.isFile() || s.size > 1048576 || s.nlink !== 1 || (privateFile && (s.uid !== process.getuid?.() || (s.mode & 0o077) !== 0)))
25
+ throw Error("Process-group authorization resource is not a bounded private regular file");
26
+ const b = fs.readFileSync(fd);
27
+ if (b.length > 1048576)
28
+ throw Error("Process-group authorization resource too large");
29
+ return b;
30
+ }
31
+ finally {
32
+ fs.closeSync(fd);
33
+ }
34
+ }
35
+ /** Pins metadata and compiled JS/JSON modules, not an installed dependency tree. */
36
+ export function groupArtifactHash(root) {
37
+ const files = ["package.json"];
38
+ let total = 0, entries = 0;
39
+ const visit = (dir, depth = 0) => {
40
+ if (depth > 32)
41
+ throw Error("Process-group artifact directory depth exceeded");
42
+ const directory = fs.opendirSync(dir);
43
+ try {
44
+ let e;
45
+ while ((e = directory.readSync())) {
46
+ if (++entries > 4096)
47
+ throw Error("Process-group artifact directory budget exceeded");
48
+ const f = path.join(dir, e.name);
49
+ if (e.isSymbolicLink())
50
+ throw Error("Process-group artifact cannot contain links");
51
+ if (e.isDirectory())
52
+ visit(f, depth + 1);
53
+ else if (e.isFile() && /\.(?:[cm]?js|json)$/.test(e.name))
54
+ files.push(path.relative(root, f));
55
+ if (files.length > 2048)
56
+ throw Error("Process-group artifact file budget exceeded");
57
+ }
58
+ }
59
+ finally {
60
+ directory.closeSync();
61
+ }
62
+ };
63
+ visit(path.join(root, "dist"));
64
+ if (files.length < 2)
65
+ throw Error("Process-group compiled artifact is missing");
66
+ return configurationAuthorizationHash(files.sort().map((f) => {
67
+ const b = readProcessGroupResource(path.join(root, f));
68
+ total += b.length;
69
+ if (total > 32 * 1024 * 1024)
70
+ throw Error("Process-group artifact byte budget exceeded");
71
+ return [f, sha256(b)];
72
+ }));
73
+ }
74
+ /** Endpoint/TLS identity only; credentials never become a policy field or diagnostic. */
75
+ export function groupChannelsHash(channels) {
76
+ if (channels.length !== 3)
77
+ throw Error("Process-group requires infra, input and output channel identities");
78
+ return configurationAuthorizationHash(channels.map((value) => {
79
+ const c = value;
80
+ if (typeof c["host"] !== "string" || !c["host"])
81
+ throw Error("Process-group broker host must be resolved");
82
+ const protocol = c["protocol"] ?? "mqtt";
83
+ return {
84
+ host: c["host"],
85
+ port: c["port"] ?? (protocol === "mqtts" ? 8883 : 1883),
86
+ protocol,
87
+ hosts: c["hosts"] ?? [],
88
+ servers: c["servers"] ?? [],
89
+ servername: c["servername"] ?? null,
90
+ rejectUnauthorized: c["rejectUnauthorized"] ?? true,
91
+ ca: c["ca"] === undefined ? null : sha256(String(c["ca"])),
92
+ cert: c["cert"] === undefined ? null : sha256(String(c["cert"])),
93
+ };
94
+ }));
95
+ }
96
+ //# sourceMappingURL=process-group-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-resources.js","sourceRoot":"","sources":["../../src/runtime/process-group-resources.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport const sha256 = (b: string | Buffer) => createHash(\"sha256\").update(b).digest(\"hex\");\nfunction canonical(v: unknown): unknown {\n if (Array.isArray(v)) return v.map(canonical);\n return v && typeof v === \"object\"\n ? Object.fromEntries(\n Object.entries(v)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, x]) => [k, canonical(x)]),\n )\n : v;\n}\nexport const configurationAuthorizationHash = (v: unknown): string => sha256(JSON.stringify(canonical(v)));\nexport function readProcessGroupResource(file: string, privateFile = false): Buffer {\n if (file.length > 512 || path.resolve(file) !== file) throw Error(\"Process-group authorization resource path is not normalized\");\n for (let p = file; p !== path.dirname(p); p = path.dirname(p))\n if (fs.lstatSync(p).isSymbolicLink()) throw Error(\"Process-group authorization resource cannot contain links\");\n const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);\n try {\n const s = fs.fstatSync(fd);\n if (!s.isFile() || s.size > 1048576 || s.nlink !== 1 || (privateFile && (s.uid !== process.getuid?.() || (s.mode & 0o077) !== 0)))\n throw Error(\"Process-group authorization resource is not a bounded private regular file\");\n const b = fs.readFileSync(fd);\n if (b.length > 1048576) throw Error(\"Process-group authorization resource too large\");\n return b;\n } finally {\n fs.closeSync(fd);\n }\n}\n/** Pins metadata and compiled JS/JSON modules, not an installed dependency tree. */\nexport function groupArtifactHash(root: string): string {\n const files = [\"package.json\"];\n let total = 0,\n entries = 0;\n const visit = (dir: string, depth = 0) => {\n if (depth > 32) throw Error(\"Process-group artifact directory depth exceeded\");\n const directory = fs.opendirSync(dir);\n try {\n let e;\n while ((e = directory.readSync())) {\n if (++entries > 4096) throw Error(\"Process-group artifact directory budget exceeded\");\n const f = path.join(dir, e.name);\n if (e.isSymbolicLink()) throw Error(\"Process-group artifact cannot contain links\");\n if (e.isDirectory()) visit(f, depth + 1);\n else if (e.isFile() && /\\.(?:[cm]?js|json)$/.test(e.name)) files.push(path.relative(root, f));\n if (files.length > 2048) throw Error(\"Process-group artifact file budget exceeded\");\n }\n } finally {\n directory.closeSync();\n }\n };\n visit(path.join(root, \"dist\"));\n if (files.length < 2) throw Error(\"Process-group compiled artifact is missing\");\n return configurationAuthorizationHash(\n files.sort().map((f) => {\n const b = readProcessGroupResource(path.join(root, f));\n total += b.length;\n if (total > 32 * 1024 * 1024) throw Error(\"Process-group artifact byte budget exceeded\");\n return [f, sha256(b)];\n }),\n );\n}\n/** Endpoint/TLS identity only; credentials never become a policy field or diagnostic. */\nexport function groupChannelsHash(channels: unknown[]): string {\n if (channels.length !== 3) throw Error(\"Process-group requires infra, input and output channel identities\");\n return configurationAuthorizationHash(\n channels.map((value) => {\n const c = value as Record<string, unknown>;\n if (typeof c[\"host\"] !== \"string\" || !c[\"host\"]) throw Error(\"Process-group broker host must be resolved\");\n const protocol = c[\"protocol\"] ?? \"mqtt\";\n return {\n host: c[\"host\"],\n port: c[\"port\"] ?? (protocol === \"mqtts\" ? 8883 : 1883),\n protocol,\n hosts: c[\"hosts\"] ?? [],\n servers: c[\"servers\"] ?? [],\n servername: c[\"servername\"] ?? null,\n rejectUnauthorized: c[\"rejectUnauthorized\"] ?? true,\n ca: c[\"ca\"] === undefined ? null : sha256(String(c[\"ca\"])),\n cert: c[\"cert\"] === undefined ? null : sha256(String(c[\"cert\"])),\n };\n }),\n );\n}\n"]}
@@ -0,0 +1,199 @@
1
+ // Fixed helper-owned program. No request-supplied paths, code, SQL or package imports.
2
+ import crypto from "node:crypto";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { DatabaseSync, backup } from "node:sqlite";
6
+
7
+ const [root, output] = process.argv.slice(2);
8
+ const hash = (b) => crypto.createHash("sha256").update(b).digest("hex");
9
+ const fileHash = (p) => {
10
+ const h = crypto.createHash("sha256"),
11
+ buffer = Buffer.alloc(64 * 1024),
12
+ fd = fs.openSync(p, "r");
13
+ try {
14
+ let n;
15
+ while ((n = fs.readSync(fd, buffer, 0, buffer.length, null))) h.update(buffer.subarray(0, n));
16
+ return h.digest("hex");
17
+ } finally {
18
+ fs.closeSync(fd);
19
+ }
20
+ };
21
+ const fail = () => {
22
+ throw Error("Persistent admission state is not safe to snapshot; preserve it and review configuration");
23
+ };
24
+ const check = (p, directory = false, optional = false) => {
25
+ let s;
26
+ try {
27
+ s = fs.lstatSync(p);
28
+ } catch (e) {
29
+ if (optional && e.code === "ENOENT") return;
30
+ throw e;
31
+ }
32
+ if (s.isSymbolicLink() || (directory ? !s.isDirectory() : !s.isFile() || s.nlink !== 1) || s.uid !== process.getuid() || (s.mode & 0o077) !== 0)
33
+ fail();
34
+ if (!directory && s.size > 512 * 1024 * 1024) fail();
35
+ };
36
+ if (
37
+ process.platform !== "linux" ||
38
+ !root ||
39
+ root !== path.resolve(root) ||
40
+ !root.startsWith("/var/lib/") ||
41
+ !output ||
42
+ output !== path.resolve(output)
43
+ )
44
+ fail();
45
+ for (let p = root; p !== "/"; p = path.dirname(p)) if (fs.lstatSync(p).isSymbolicLink()) fail();
46
+ check(root, true);
47
+ check(output, true);
48
+ const mount = fs
49
+ .readFileSync("/proc/self/mountinfo", "utf8")
50
+ .split("\n")
51
+ .map((s) => s.split(" "))
52
+ .find((f) => f[4] === root);
53
+ if (!mount || !["ext4", "xfs", "btrfs", "zfs"].includes(mount[mount.indexOf("-") + 1])) fail();
54
+
55
+ let capturedBytes = 0,
56
+ snapshotBytes = 0;
57
+ const manifest = {
58
+ schemaVersion: 1,
59
+ kind: "uns-process-group-journal-snapshot",
60
+ capturedAt: new Date().toISOString(),
61
+ groups: [],
62
+ restorePolicy: "offline-review-required-no-automatic-replay",
63
+ };
64
+ // A configured empty volume is explicit empty coverage, never confused with absent configuration.
65
+ const rootEntries = fs.readdirSync(root, { withFileTypes: true });
66
+ if (rootEntries.length > 128 || rootEntries.some((e) => e.isSymbolicLink())) fail();
67
+ const namespaces = rootEntries
68
+ .filter((e) => e.isDirectory())
69
+ .map((e) => e.name)
70
+ .sort();
71
+ if (namespaces.length > 64) fail();
72
+ const capturedGroups = new Set();
73
+ for (const namespace of namespaces) {
74
+ if (!/^[a-z][a-z0-9-]{0,99}$/.test(namespace)) fail();
75
+ const namespaceRoot = path.join(root, namespace),
76
+ admittedRoot = path.join(namespaceRoot, "admission");
77
+ check(namespaceRoot, true);
78
+ try {
79
+ fs.lstatSync(admittedRoot);
80
+ } catch (e) {
81
+ if (e.code === "ENOENT") continue;
82
+ throw e;
83
+ }
84
+ check(admittedRoot, true);
85
+ const groups = fs.readdirSync(admittedRoot).sort();
86
+ if (groups.length > 9) fail();
87
+ for (const group of groups) {
88
+ if (!/^[a-z][a-z0-9-]{0,99}$/.test(group) || capturedGroups.has(group) || capturedGroups.size >= 9) fail();
89
+ capturedGroups.add(group);
90
+ const source = path.join(admittedRoot, group);
91
+ check(source, true);
92
+ for (const name of ["admission.sqlite", "ownership.sqlite"]) {
93
+ check(path.join(source, name));
94
+ for (const suffix of ["-wal", "-shm", "-journal"]) check(path.join(source, name + suffix), false, true);
95
+ }
96
+ const sourceSize = ["admission.sqlite", "admission.sqlite-wal", "ownership.sqlite", "ownership.sqlite-journal"].reduce((total, name) => {
97
+ try {
98
+ return total + fs.statSync(path.join(source, name)).size;
99
+ } catch (e) {
100
+ if (e.code === "ENOENT") return total;
101
+ throw e;
102
+ }
103
+ }, 0);
104
+ capturedBytes += sourceSize;
105
+ if (capturedBytes > 512 * 1024 * 1024) fail();
106
+ const space = fs.statfsSync(output, { bigint: true });
107
+ if (space.bavail * space.bsize < BigInt(sourceSize * 2 + 64 * 1024 * 1024)) fail();
108
+ const target = path.join(output, group);
109
+ fs.mkdirSync(target, { mode: 0o700 });
110
+ const owner = new DatabaseSync(path.join(source, "ownership.sqlite"), { readOnly: true });
111
+ let db;
112
+ try {
113
+ owner.exec("PRAGMA busy_timeout=1000; BEGIN");
114
+ if (!owner.prepare("SELECT value FROM namespace WHERE id=1").get()?.value) fail(); // Holds namespace replacement out for both snapshots.
115
+ db = new DatabaseSync(path.join(source, "admission.sqlite"), { readOnly: true });
116
+ db.exec("PRAGMA busy_timeout=3000");
117
+ const pageSize = Number(db.prepare("PRAGMA page_size").get().page_size);
118
+ if (!Number.isSafeInteger(pageSize) || pageSize < 512 || pageSize > 65536) fail();
119
+ await backup(db, path.join(target, "admission.sqlite"), {
120
+ rate: 128,
121
+ progress: ({ totalPages }) => {
122
+ const bytes = totalPages * pageSize,
123
+ space = fs.statfsSync(output, { bigint: true });
124
+ if (
125
+ !Number.isSafeInteger(bytes) ||
126
+ bytes > 512 * 1024 * 1024 - snapshotBytes ||
127
+ space.bavail * space.bsize < BigInt(bytes + 64 * 1024 * 1024)
128
+ )
129
+ fail();
130
+ },
131
+ });
132
+ await backup(owner, path.join(target, "ownership.sqlite"), { rate: 128 });
133
+ } finally {
134
+ db?.close();
135
+ owner.close();
136
+ }
137
+ for (const name of ["admission.sqlite", "ownership.sqlite"]) fs.chmodSync(path.join(target, name), 0o600);
138
+ const snap = new DatabaseSync(path.join(target, "admission.sqlite"));
139
+ let info;
140
+ try {
141
+ if (snap.prepare("PRAGMA quick_check").get().quick_check !== "ok") fail();
142
+ const meta = Object.fromEntries(
143
+ snap
144
+ .prepare("SELECT key,value FROM metadata")
145
+ .all()
146
+ .map((v) => [v.key, v.value]),
147
+ );
148
+ if (!/^[0-9a-f-]{36}$/.test(meta.id ?? "")) fail();
149
+ const contract = JSON.parse(meta.contract);
150
+ const profiles = snap.prepare("SELECT name,contract,completed,last_seq FROM profiles ORDER BY name").all();
151
+ if (profiles.length < 1 || profiles.length > 19 || contract.version !== 1 || contract.profiles.length !== profiles.length) fail();
152
+ const usage = snap.prepare("SELECT records,bytes,admitted FROM usage WHERE id=1").get();
153
+ const actual = snap.prepare("SELECT count(*) records,coalesce(sum(bytes),0) bytes FROM tasks").get();
154
+ if (
155
+ !usage ||
156
+ usage.records !== actual.records ||
157
+ usage.bytes !== actual.bytes ||
158
+ usage.records > contract.maxRecords ||
159
+ usage.bytes > contract.maxBytes
160
+ )
161
+ fail();
162
+ info = {
163
+ group,
164
+ namespace,
165
+ journalId: meta.id,
166
+ clientId: namespace + "-admission-" + meta.id,
167
+ contractSha256: hash(meta.contract),
168
+ usage,
169
+ profiles: profiles.map((p) => ({ name: p.name, contractSha256: hash(p.contract), completed: p.completed, lastSeq: p.last_seq })),
170
+ };
171
+ } finally {
172
+ snap.close();
173
+ }
174
+ // Snapshot may have WAL mode persisted; force a self-contained DB and no sidecars.
175
+ for (const name of ["admission.sqlite", "ownership.sqlite"]) {
176
+ const p = path.join(target, name);
177
+ const d = new DatabaseSync(p);
178
+ try {
179
+ d.exec("PRAGMA wal_checkpoint(TRUNCATE); PRAGMA journal_mode=DELETE");
180
+ } finally {
181
+ d.close();
182
+ }
183
+ const fd = fs.openSync(p, "r");
184
+ try {
185
+ fs.fsyncSync(fd);
186
+ } finally {
187
+ fs.closeSync(fd);
188
+ }
189
+ snapshotBytes += fs.statSync(p).size;
190
+ if (snapshotBytes > 512 * 1024 * 1024) fail();
191
+ info[name === "admission.sqlite" ? "admissionSha256" : "ownershipSha256"] = fileHash(p);
192
+ }
193
+ manifest.groups.push(info);
194
+ }
195
+ }
196
+ const remaining = fs.statfsSync(output, { bigint: true });
197
+ if (remaining.bavail * remaining.bsize < BigInt(snapshotBytes + 64 * 1024 * 1024)) fail();
198
+ fs.writeFileSync(path.join(output, "manifest.json"), JSON.stringify(manifest) + "\n", { mode: 0o600, flag: "wx" });
199
+ // No source payloads, credentials, paths or process metadata on stdout/stderr.
@@ -0,0 +1,5 @@
1
+ import { type ProcessGroupRuntimeDescriptor } from "./process-group-contract.js";
2
+ export declare const stagedJournalFile = "process-group-staged-journal.json";
3
+ /** An explicit, config-bound declaration, not permission to initialize or run. */
4
+ export declare function refreshProcessGroupStagedJournal(instanceDir: string, stopped: boolean, descriptor: ProcessGroupRuntimeDescriptor | undefined): void;
5
+ //# sourceMappingURL=process-group-staging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-staging.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-staging.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,6BAA6B,EAAsC,MAAM,6BAA6B,CAAC;AAErH,eAAO,MAAM,iBAAiB,sCAAsC,CAAC;AACrE,kFAAkF;AAClF,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,6BAA6B,GAAG,SAAS,GAAG,IAAI,CAmDnJ"}
@@ -0,0 +1,63 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { normalizeProcessGroupConfiguration } from "./process-group-contract.js";
5
+ export const stagedJournalFile = "process-group-staged-journal.json";
6
+ /** An explicit, config-bound declaration, not permission to initialize or run. */
7
+ export function refreshProcessGroupStagedJournal(instanceDir, stopped, descriptor) {
8
+ const marker = path.join(instanceDir, stagedJournalFile);
9
+ const configFile = path.join(instanceDir, "config.json");
10
+ if (!fs.existsSync(configFile))
11
+ return;
12
+ const stat = fs.lstatSync(configFile);
13
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024)
14
+ throw new Error("Staged configuration must be a bounded regular file.");
15
+ const raw = fs.readFileSync(configFile);
16
+ const config = JSON.parse(raw.toString("utf8"));
17
+ const journal = descriptor
18
+ ? normalizeProcessGroupConfiguration(config, descriptor).journal
19
+ : undefined;
20
+ if (!stopped || !journal || journal.journalId !== undefined) {
21
+ fs.rmSync(marker, { force: true });
22
+ return;
23
+ }
24
+ if (typeof journal.directory !== "string" || !path.isAbsolute(journal.directory) || path.normalize(journal.directory) !== journal.directory)
25
+ throw new Error("Staged journal requires a normalized absolute directory.");
26
+ // Existing/unknown data must never be declared uninitialized, including links.
27
+ for (let dir = journal.directory; dir !== path.dirname(dir); dir = path.dirname(dir)) {
28
+ try {
29
+ const stat = fs.lstatSync(dir);
30
+ if (stat.isSymbolicLink() || dir === journal.directory)
31
+ throw new Error("Existing journal cannot be marked uninitialized.");
32
+ }
33
+ catch (error) {
34
+ if (error.code !== "ENOENT")
35
+ throw error;
36
+ }
37
+ }
38
+ if (fs.existsSync(path.join(instanceDir, "handover-source-guard.json.launch")))
39
+ throw new Error("A previously launched instance requires journal review.");
40
+ const temporary = marker + "." + randomUUID() + ".tmp";
41
+ const fd = fs.openSync(temporary, "wx", 0o600);
42
+ try {
43
+ fs.writeFileSync(fd, JSON.stringify({
44
+ schemaVersion: 1,
45
+ kind: "uns-process-group-staged-journal",
46
+ configurationSha256: createHash("sha256").update(raw).digest("hex"),
47
+ directory: journal.directory,
48
+ }) + "\n");
49
+ fs.fsyncSync(fd);
50
+ }
51
+ finally {
52
+ fs.closeSync(fd);
53
+ }
54
+ fs.renameSync(temporary, marker);
55
+ const parent = fs.openSync(instanceDir, "r");
56
+ try {
57
+ fs.fsyncSync(parent);
58
+ }
59
+ finally {
60
+ fs.closeSync(parent);
61
+ }
62
+ }
63
+ //# sourceMappingURL=process-group-staging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-staging.js","sourceRoot":"","sources":["../../src/runtime/process-group-staging.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { type ProcessGroupRuntimeDescriptor, normalizeProcessGroupConfiguration } from \"./process-group-contract.js\";\n\nexport const stagedJournalFile = \"process-group-staged-journal.json\";\n/** An explicit, config-bound declaration, not permission to initialize or run. */\nexport function refreshProcessGroupStagedJournal(instanceDir: string, stopped: boolean, descriptor: ProcessGroupRuntimeDescriptor | undefined): void {\n const marker = path.join(instanceDir, stagedJournalFile);\n const configFile = path.join(instanceDir, \"config.json\");\n if (!fs.existsSync(configFile)) return;\n const stat = fs.lstatSync(configFile);\n if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1024 * 1024) throw new Error(\"Staged configuration must be a bounded regular file.\");\n const raw = fs.readFileSync(configFile);\n const config = JSON.parse(raw.toString(\"utf8\")) as Record<string, unknown>;\n const journal = descriptor\n ? (normalizeProcessGroupConfiguration(config, descriptor).journal as { directory?: unknown; journalId?: unknown } | undefined)\n : undefined;\n if (!stopped || !journal || journal.journalId !== undefined) {\n fs.rmSync(marker, { force: true });\n return;\n }\n if (typeof journal.directory !== \"string\" || !path.isAbsolute(journal.directory) || path.normalize(journal.directory) !== journal.directory)\n throw new Error(\"Staged journal requires a normalized absolute directory.\");\n // Existing/unknown data must never be declared uninitialized, including links.\n for (let dir = journal.directory; dir !== path.dirname(dir); dir = path.dirname(dir)) {\n try {\n const stat = fs.lstatSync(dir);\n if (stat.isSymbolicLink() || dir === journal.directory) throw new Error(\"Existing journal cannot be marked uninitialized.\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n }\n }\n if (fs.existsSync(path.join(instanceDir, \"handover-source-guard.json.launch\")))\n throw new Error(\"A previously launched instance requires journal review.\");\n const temporary = marker + \".\" + randomUUID() + \".tmp\";\n const fd = fs.openSync(temporary, \"wx\", 0o600);\n try {\n fs.writeFileSync(\n fd,\n JSON.stringify({\n schemaVersion: 1,\n kind: \"uns-process-group-staged-journal\",\n configurationSha256: createHash(\"sha256\").update(raw).digest(\"hex\"),\n directory: journal.directory,\n }) + \"\\n\",\n );\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n fs.renameSync(temporary, marker);\n const parent = fs.openSync(instanceDir, \"r\");\n try {\n fs.fsyncSync(parent);\n } finally {\n fs.closeSync(parent);\n }\n}\n"]}
@@ -0,0 +1,13 @@
1
+ import { type ProcessGroupRuntimeDescriptor } from "./process-group-contract.js";
2
+ /** SDK receiver contract; host launchers translate these neutral settings to PM2/systemd. */
3
+ export declare function processGroupReceiverSupervision(raw: Record<string, unknown>, descriptor: ProcessGroupRuntimeDescriptor | undefined, instanceDirectory: string, capabilities: {
4
+ supervised: boolean;
5
+ persistent: boolean;
6
+ authorized: boolean;
7
+ }, supervisor: {
8
+ enabled: boolean;
9
+ restartOnExit: boolean;
10
+ restartOnUnhealthy: boolean;
11
+ maxMemoryMb?: number | null;
12
+ }): Record<string, unknown>;
13
+ //# sourceMappingURL=process-group-supervision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-supervision.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-supervision.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,6BAA6B,EAAwD,MAAM,6BAA6B,CAAC;AAEvI,6FAA6F;AAC7F,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,UAAU,EAAE,6BAA6B,GAAG,SAAS,EACrD,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,EAC/E,UAAU,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,kBAAkB,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACjH,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBzB"}
@@ -0,0 +1,34 @@
1
+ import { isUnsupportedLegacyReceiver } from "./compatibility/energenti-descriptor-v1.js";
2
+ import { isLocalPilotPath, normalizeProcessGroupConfiguration } from "./process-group-contract.js";
3
+ /** SDK receiver contract; host launchers translate these neutral settings to PM2/systemd. */
4
+ export function processGroupReceiverSupervision(raw, descriptor, instanceDirectory, capabilities, supervisor) {
5
+ if (!descriptor) {
6
+ if (isUnsupportedLegacyReceiver(raw))
7
+ throw Error("Installed package has no supported receiver contract");
8
+ return {};
9
+ }
10
+ const c = normalizeProcessGroupConfiguration(raw, descriptor);
11
+ if (c.runtimeRole !== "admission")
12
+ return {};
13
+ if (!c.matches || !c.journal || (!isLocalPilotPath(instanceDirectory) && !capabilities.authorized))
14
+ throw Error("Admission supervision requires an explicit reviewed journal instance");
15
+ if (!capabilities.supervised)
16
+ throw Error("Installed package does not support the supervised admission role");
17
+ const directory = c.journal["directory"];
18
+ if (typeof directory === "string" && !isLocalPilotPath(directory) && !capabilities.persistent)
19
+ throw Error("Installed package does not support persistent admission ownership");
20
+ if (!supervisor.enabled || !supervisor.restartOnExit || supervisor.restartOnUnhealthy)
21
+ throw Error("Admission requires restart-on-exit supervision; generic MQTT unhealthy restart is unsupported");
22
+ const max = supervisor.maxMemoryMb ?? 256;
23
+ if (max < 128 || max > 4096)
24
+ throw Error("Admission supervisor memory limit must be 128–4096 MiB");
25
+ return {
26
+ autorestart: true,
27
+ stop_exit_codes: [78],
28
+ min_uptime: 10000,
29
+ max_restarts: 5,
30
+ exp_backoff_restart_delay: 1000,
31
+ max_memory_restart: `${max}M`,
32
+ };
33
+ }
34
+ //# sourceMappingURL=process-group-supervision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-supervision.js","sourceRoot":"","sources":["../../src/runtime/process-group-supervision.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAsC,gBAAgB,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AAEvI,6FAA6F;AAC7F,MAAM,UAAU,+BAA+B,CAC7C,GAA4B,EAC5B,UAAqD,EACrD,iBAAyB,EACzB,YAA+E,EAC/E,UAAkH;IAElH,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,IAAI,2BAA2B,CAAC,GAAG,CAAC;YAAE,MAAM,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1G,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,CAAC,GAAG,kCAAkC,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC;IAC7C,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;QAChG,MAAM,KAAK,CAAC,sEAAsE,CAAC,CAAC;IACtF,IAAI,CAAC,YAAY,CAAC,UAAU;QAAE,MAAM,KAAK,CAAC,kEAAkE,CAAC,CAAC;IAC9G,MAAM,SAAS,GAAI,CAAC,CAAC,OAAmC,CAAC,WAAW,CAAC,CAAC;IACtE,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU;QAC3F,MAAM,KAAK,CAAC,mEAAmE,CAAC,CAAC;IACnF,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,IAAI,UAAU,CAAC,kBAAkB;QACnF,MAAM,KAAK,CAAC,+FAA+F,CAAC,CAAC;IAC/G,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,IAAI,GAAG,CAAC;IAC1C,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI;QAAE,MAAM,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACnG,OAAO;QACL,WAAW,EAAE,IAAI;QACjB,eAAe,EAAE,CAAC,EAAE,CAAC;QACrB,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,CAAC;QACf,yBAAyB,EAAE,IAAI;QAC/B,kBAAkB,EAAE,GAAG,GAAG,GAAG;KAC9B,CAAC;AACJ,CAAC","sourcesContent":["import { isUnsupportedLegacyReceiver } from \"./compatibility/energenti-descriptor-v1.js\";\nimport { type ProcessGroupRuntimeDescriptor, isLocalPilotPath, normalizeProcessGroupConfiguration } from \"./process-group-contract.js\";\n\n/** SDK receiver contract; host launchers translate these neutral settings to PM2/systemd. */\nexport function processGroupReceiverSupervision(\n raw: Record<string, unknown>,\n descriptor: ProcessGroupRuntimeDescriptor | undefined,\n instanceDirectory: string,\n capabilities: { supervised: boolean; persistent: boolean; authorized: boolean },\n supervisor: { enabled: boolean; restartOnExit: boolean; restartOnUnhealthy: boolean; maxMemoryMb?: number | null },\n): Record<string, unknown> {\n if (!descriptor) {\n if (isUnsupportedLegacyReceiver(raw)) throw Error(\"Installed package has no supported receiver contract\");\n return {};\n }\n const c = normalizeProcessGroupConfiguration(raw, descriptor);\n if (c.runtimeRole !== \"admission\") return {};\n if (!c.matches || !c.journal || (!isLocalPilotPath(instanceDirectory) && !capabilities.authorized))\n throw Error(\"Admission supervision requires an explicit reviewed journal instance\");\n if (!capabilities.supervised) throw Error(\"Installed package does not support the supervised admission role\");\n const directory = (c.journal as Record<string, unknown>)[\"directory\"];\n if (typeof directory === \"string\" && !isLocalPilotPath(directory) && !capabilities.persistent)\n throw Error(\"Installed package does not support persistent admission ownership\");\n if (!supervisor.enabled || !supervisor.restartOnExit || supervisor.restartOnUnhealthy)\n throw Error(\"Admission requires restart-on-exit supervision; generic MQTT unhealthy restart is unsupported\");\n const max = supervisor.maxMemoryMb ?? 256;\n if (max < 128 || max > 4096) throw Error(\"Admission supervisor memory limit must be 128–4096 MiB\");\n return {\n autorestart: true,\n stop_exit_codes: [78],\n min_uptime: 10000,\n max_restarts: 5,\n exp_backoff_restart_delay: 1000,\n max_memory_restart: `${max}M`,\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { GeneratedAttributes } from "./uns-dictionary.generated.js";
2
- export declare const knownUnsAttributes: ("level" | "active-energy-delivered" | "active-energy-received" | "alarm" | "assigned-to" | "authorization-level" | "availability" | "batch-number" | "conductivity" | "consumption" | "consumption-rate" | "cost" | "current" | "deviation" | "downtime" | "duration" | "end-time" | "energy" | "energy-consumption" | "fault-code" | "flow" | "frequency" | "hardness" | "inspection-result" | "instruction-url" | "last-refill" | "location" | "lot-id" | "maintenance-status" | "material-composition" | "material-type" | "operating-hours" | "operator-id" | "output-quantity" | "pass-fail" | "ph" | "planned-end" | "planned-start" | "power" | "presence" | "pressure" | "product-code" | "quantity" | "reactive-energy-delivered" | "reactive-energy-received" | "refill-required" | "revision" | "role" | "specification" | "speed" | "start-time" | "status" | "surface-defect" | "target-parameters" | "task-id" | "task-list" | "temperature" | "tensile-strength" | "total-flow" | "utilization" | "version-history" | "vibration" | "voltage" | "work-order-id")[];
2
+ export declare const knownUnsAttributes: ("level" | "revision" | "active-energy-delivered" | "active-energy-received" | "alarm" | "assigned-to" | "authorization-level" | "availability" | "batch-number" | "conductivity" | "consumption" | "consumption-rate" | "cost" | "current" | "deviation" | "downtime" | "duration" | "end-time" | "energy" | "energy-consumption" | "fault-code" | "flow" | "frequency" | "hardness" | "inspection-result" | "instruction-url" | "last-refill" | "location" | "lot-id" | "maintenance-status" | "material-composition" | "material-type" | "operating-hours" | "operator-id" | "output-quantity" | "pass-fail" | "ph" | "planned-end" | "planned-start" | "power" | "presence" | "pressure" | "product-code" | "quantity" | "reactive-energy-delivered" | "reactive-energy-received" | "refill-required" | "role" | "specification" | "speed" | "start-time" | "status" | "surface-defect" | "target-parameters" | "task-id" | "task-list" | "temperature" | "tensile-strength" | "total-flow" | "utilization" | "version-history" | "vibration" | "voltage" | "work-order-id")[];
3
3
  export type KnownUnsAttributeName = typeof GeneratedAttributes[keyof typeof GeneratedAttributes];
4
4
  export type UnsAttribute = "" | KnownUnsAttributeName | (string & {});
5
- export declare const AttributeDescriptions: Record<"level" | "active-energy-delivered" | "active-energy-received" | "alarm" | "assigned-to" | "authorization-level" | "availability" | "batch-number" | "conductivity" | "consumption" | "consumption-rate" | "cost" | "current" | "deviation" | "downtime" | "duration" | "end-time" | "energy" | "energy-consumption" | "fault-code" | "flow" | "frequency" | "hardness" | "inspection-result" | "instruction-url" | "last-refill" | "location" | "lot-id" | "maintenance-status" | "material-composition" | "material-type" | "operating-hours" | "operator-id" | "output-quantity" | "pass-fail" | "ph" | "planned-end" | "planned-start" | "power" | "presence" | "pressure" | "product-code" | "quantity" | "reactive-energy-delivered" | "reactive-energy-received" | "refill-required" | "revision" | "role" | "specification" | "speed" | "start-time" | "status" | "surface-defect" | "target-parameters" | "task-id" | "task-list" | "temperature" | "tensile-strength" | "total-flow" | "utilization" | "version-history" | "vibration" | "voltage" | "work-order-id", string>;
5
+ export declare const AttributeDescriptions: Record<"level" | "revision" | "active-energy-delivered" | "active-energy-received" | "alarm" | "assigned-to" | "authorization-level" | "availability" | "batch-number" | "conductivity" | "consumption" | "consumption-rate" | "cost" | "current" | "deviation" | "downtime" | "duration" | "end-time" | "energy" | "energy-consumption" | "fault-code" | "flow" | "frequency" | "hardness" | "inspection-result" | "instruction-url" | "last-refill" | "location" | "lot-id" | "maintenance-status" | "material-composition" | "material-type" | "operating-hours" | "operator-id" | "output-quantity" | "pass-fail" | "ph" | "planned-end" | "planned-start" | "power" | "presence" | "pressure" | "product-code" | "quantity" | "reactive-energy-delivered" | "reactive-energy-received" | "refill-required" | "role" | "specification" | "speed" | "start-time" | "status" | "surface-defect" | "target-parameters" | "task-id" | "task-list" | "temperature" | "tensile-strength" | "total-flow" | "utilization" | "version-history" | "vibration" | "voltage" | "work-order-id", string>;
6
6
  export declare function getAttributeDescription(name: string): string | undefined;
7
7
  //# sourceMappingURL=uns-attributes.d.ts.map
@@ -29,6 +29,8 @@ export default class MqttProxy {
29
29
  private subscribedMessageBytes;
30
30
  private mqttWorker;
31
31
  isConnected: boolean;
32
+ private subscriptionReadiness;
33
+ private lastSubscriptionReady;
32
34
  private rejectUnauthorized;
33
35
  private pendingReconnectWait;
34
36
  private hasEstablishedConnection;
@@ -40,6 +42,7 @@ export default class MqttProxy {
40
42
  private resolveDefaultPort;
41
43
  private ensureStatusUpdateInterval;
42
44
  private ensureTransformationStatsInterval;
45
+ private emitSubscriptionReadiness;
43
46
  private subscribeToTopics;
44
47
  private buildServers;
45
48
  start(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,IAAoC,MAAM,MAAM,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CAC/B,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,SAAS;IACrB,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAoC;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,2BAA2B,CAA+B;IAClE,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,UAAU,CAAa;IACxB,WAAW,UAAS;IAC3B,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,aAAa,CAA2C;gBAEpD,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU;IAY5G,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,0BAA0B;IAMlC,OAAO,CAAC,iCAAiC;IAQzC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;IA0CP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiHtB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BrG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAIpH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IASlF,IAAI,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkDzD,OAAO,CAAC,iBAAiB;IAoCzB,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,kCAAkC;IAK1C,OAAO,CAAC,gBAAgB;YAsCV,4BAA4B;CAwC3C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAY7D"}
1
+ {"version":3,"file":"mqtt-proxy.d.ts","sourceRoot":"","sources":["../../src/uns-mqtt/mqtt-proxy.ts"],"names":[],"mappings":"AACA,OAAO,IAAoC,MAAM,MAAM,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CAC/B,CAAC;AAEF,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,SAAS;IACrB,KAAK,EAAE,eAAe,CAAC,SAAS,CAAC,CAAoC;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,SAAS,CAAO;IACxB,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,oBAAoB,CAAiC;IAC7D,OAAO,CAAC,2BAA2B,CAA+B;IAClE,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,qBAAqB,CAAK;IAClC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,UAAU,CAAa;IACxB,WAAW,UAAS;IAC3B,OAAO,CAAC,qBAAqB,CAA+B;IAC5D,OAAO,CAAC,qBAAqB,CAAwB;IACrD,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,oBAAoB,CAA8B;IAC1D,OAAO,CAAC,wBAAwB,CAAS;IACzC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,aAAa,CAA2C;gBAEpD,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU;IAY5G,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,0BAA0B;IAMlC,OAAO,CAAC,iCAAiC;IAQzC,OAAO,CAAC,yBAAyB;IAQjC,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,YAAY;IA0CP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqItB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BrG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAIpH,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IASlF,IAAI,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDzD,OAAO,CAAC,iBAAiB;IAwCzB,OAAO,CAAC,iBAAiB;IAkBzB,OAAO,CAAC,gCAAgC;IAKxC,OAAO,CAAC,kCAAkC;IAK1C,OAAO,CAAC,gBAAgB;YAsCV,4BAA4B;CAwC3C;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAY7D"}