@uns-kit/core 3.0.32 → 3.0.34

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 (60) hide show
  1. package/MIGRATIONS.md +41 -0
  2. package/dist/config/app-config.d.ts +1 -0
  3. package/dist/config/app-config.d.ts.map +1 -1
  4. package/dist/config/app-config.js.map +1 -1
  5. package/dist/runtime/mqtt-drain.d.ts +29 -0
  6. package/dist/runtime/mqtt-drain.d.ts.map +1 -0
  7. package/dist/runtime/mqtt-drain.js +70 -0
  8. package/dist/runtime/mqtt-drain.js.map +1 -0
  9. package/dist/runtime/mqtt-output-state-contract.d.ts.map +1 -1
  10. package/dist/runtime/mqtt-output-state-contract.js +2 -0
  11. package/dist/runtime/mqtt-output-state-contract.js.map +1 -1
  12. package/dist/runtime/process-group-authorization.d.ts +72 -0
  13. package/dist/runtime/process-group-authorization.d.ts.map +1 -1
  14. package/dist/runtime/process-group-authorization.js +31 -0
  15. package/dist/runtime/process-group-authorization.js.map +1 -1
  16. package/dist/runtime/process-group-contract.d.ts +1 -0
  17. package/dist/runtime/process-group-contract.d.ts.map +1 -1
  18. package/dist/runtime/process-group-contract.js +2 -1
  19. package/dist/runtime/process-group-contract.js.map +1 -1
  20. package/dist/runtime/process-group-direct-contract.d.ts +181 -0
  21. package/dist/runtime/process-group-direct-contract.d.ts.map +1 -0
  22. package/dist/runtime/process-group-direct-contract.js +151 -0
  23. package/dist/runtime/process-group-direct-contract.js.map +1 -0
  24. package/dist/runtime/process-group-direct-review.d.ts +203 -0
  25. package/dist/runtime/process-group-direct-review.d.ts.map +1 -0
  26. package/dist/runtime/process-group-direct-review.js +263 -0
  27. package/dist/runtime/process-group-direct-review.js.map +1 -0
  28. package/dist/runtime/process-group-direct-runtime.d.ts +18 -0
  29. package/dist/runtime/process-group-direct-runtime.d.ts.map +1 -0
  30. package/dist/runtime/process-group-direct-runtime.js +154 -0
  31. package/dist/runtime/process-group-direct-runtime.js.map +1 -0
  32. package/dist/runtime/process-group-snapshot.mjs +44 -0
  33. package/dist/uns/uns-proxy-process.d.ts +8 -4
  34. package/dist/uns/uns-proxy-process.d.ts.map +1 -1
  35. package/dist/uns/uns-proxy-process.js +41 -5
  36. package/dist/uns/uns-proxy-process.js.map +1 -1
  37. package/dist/uns-config/config-schema.d.ts +1 -0
  38. package/dist/uns-config/config-schema.d.ts.map +1 -1
  39. package/dist/uns-config/uns-core-schema.d.ts +2 -0
  40. package/dist/uns-config/uns-core-schema.d.ts.map +1 -1
  41. package/dist/uns-mqtt/disabled-publish-queue.d.ts +6 -0
  42. package/dist/uns-mqtt/disabled-publish-queue.d.ts.map +1 -0
  43. package/dist/uns-mqtt/disabled-publish-queue.js +64 -0
  44. package/dist/uns-mqtt/disabled-publish-queue.js.map +1 -0
  45. package/dist/uns-mqtt/mqtt-proxy.d.ts +1 -0
  46. package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
  47. package/dist/uns-mqtt/mqtt-proxy.js +5 -0
  48. package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
  49. package/dist/uns-mqtt/publish-queue-contract.d.ts +2 -0
  50. package/dist/uns-mqtt/publish-queue-contract.d.ts.map +1 -1
  51. package/dist/uns-mqtt/publish-queue-contract.js +4 -0
  52. package/dist/uns-mqtt/publish-queue-contract.js.map +1 -1
  53. package/dist/uns-mqtt/publish-queue.d.ts.map +1 -1
  54. package/dist/uns-mqtt/publish-queue.js +2 -0
  55. package/dist/uns-mqtt/publish-queue.js.map +1 -1
  56. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +9 -0
  57. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts.map +1 -1
  58. package/dist/uns-mqtt/uns-mqtt-proxy.js +31 -1
  59. package/dist/uns-mqtt/uns-mqtt-proxy.js.map +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-direct-review.js","sourceRoot":"","sources":["../../src/runtime/process-group-direct-review.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { configurationGroupSnapshot, configurationResourceHash } from \"./configuration-group-contract.js\";\nimport { authorizeProcessGroupRuntime, processGroupManifestSchema } from \"./process-group-authorization.js\";\nimport {\n processGroupJournalContract,\n processGroupJournalSchema,\n processGroupSourceIdentity,\n readConfigurationSelector,\n resolvedProcessGroupChannels,\n} from \"./process-group-contract.js\";\nimport {\n type ProcessGroupDirectDescriptor,\n type ProcessGroupDirectInput,\n processGroupDirectDescriptorSchema,\n processGroupDirectInputSchema,\n processGroupRetirementPolicySchema,\n retiredJournalReferenceSchema,\n} from \"./process-group-direct-contract.js\";\nimport { describeInstalledProcessGroupGeneration, inspectGenerationJournal } from \"./process-group-generation.js\";\nimport type { GenerationJournalReference } from \"./process-group-generation.js\";\nimport {\n groupArtifactHash,\n groupChannelsHash,\n configurationAuthorizationHash as hash,\n readProcessGroupResource as read,\n sha256,\n} from \"./process-group-resources.js\";\nimport { normalizeRuntimeProcessGroup, selectedProcessGroupDescriptor } from \"./process-group-runtime-selection.js\";\nimport type { UpgradeConfiguration } from \"./process-group-upgrade.js\";\n\ntype Config = UpgradeConfiguration;\nexport type DirectTransitionConfigurations = { source: { publisher: Config; receiver: Config }; target: Config };\nconst inside = (root: string, file: string) => {\n const resolved = path.resolve(root, file);\n if (!resolved.startsWith(path.resolve(root) + path.sep)) throw Error(\"Direct resource escapes installed package\");\n return read(resolved);\n};\nexport function processGroupDirectDescriptor(packageRoot: string): ProcessGroupDirectDescriptor | undefined {\n const pkg = JSON.parse(read(path.join(packageRoot, \"package.json\")).toString());\n return pkg.unsDatahub?.processGroupDirectRuntime === undefined\n ? undefined\n : processGroupDirectDescriptorSchema.parse(pkg.unsDatahub.processGroupDirectRuntime);\n}\nexport function describeDirectProcessGroup(c: Config) {\n const descriptor = processGroupDirectDescriptor(c.packageRoot);\n if (\n !descriptor ||\n (descriptor.match && readConfigurationSelector(c.raw, descriptor.match.path) !== descriptor.match.value) ||\n readConfigurationSelector(c.raw, descriptor.runtimeRolePath) !== descriptor.directRole ||\n readConfigurationSelector(c.raw, descriptor.journalPath) !== undefined\n )\n throw Error(\"Exact declared direct mode without an input journal required\");\n const publisher = readConfigurationSelector(c.raw, descriptor.publisherPath);\n if (!publisher || typeof publisher !== \"object\" || Array.isArray(publisher)) throw Error(\"Explicit direct publisher required\");\n const selectedResources = descriptor.resources.filter(\n (r) => readConfigurationSelector(c.raw, r.kind === \"file\" ? r.manifestPath : r.groupPath) !== undefined,\n );\n if (selectedResources.length !== 1) throw Error(\"Select exactly one declared direct resource\");\n const resource = selectedResources[0]!;\n if (resource.kind === \"configuration\") {\n const snapshot = configurationGroupSnapshot(readConfigurationSelector(c.raw, resource.groupPath));\n if (\n configurationResourceHash(readConfigurationSelector(c.resolved, resource.groupPath)) !==\n configurationResourceHash(readConfigurationSelector(c.raw, resource.groupPath))\n )\n throw Error(\"Resolved direct business resource differs from its reviewed configuration\");\n return {\n descriptor,\n resource,\n groupId: snapshot.group.id,\n processName: snapshot.group.processName,\n resourceSha256: snapshot.sha256,\n profiles: snapshot.profiles.map((p) => ({ processName: p.processName, mappingSha256: p.resourceSha256, dataGroup: p.dataGroup })),\n snapshot,\n };\n }\n const manifestPath = readConfigurationSelector(c.raw, resource.manifestPath);\n const selected = resource.manifests.find((m) => m.file === manifestPath);\n if (!selected) throw Error(\"Unregistered direct manifest\");\n if (readConfigurationSelector(c.resolved, resource.manifestPath) !== selected.file) throw Error(\"Resolved direct manifest selection changed\");\n const bytes = inside(c.packageRoot, selected.file),\n manifest = processGroupManifestSchema.parse(JSON.parse(bytes.toString()));\n if (manifest.id !== selected.id) throw Error(\"Direct manifest identity differs\");\n for (const p of manifest.profiles)\n if (sha256(inside(c.packageRoot, path.join(path.dirname(selected.file), p.mappingFile))) !== p.mappingSha256)\n throw Error(\"Direct profile resource changed\");\n return {\n descriptor,\n resource,\n groupId: manifest.id,\n processName: manifest.processName,\n resourceSha256: sha256(bytes),\n profiles: manifest.profiles.map(({ processName, mappingSha256, dataGroup }) => ({ processName, mappingSha256, dataGroup })),\n manifest,\n manifestPath: selected.file,\n manifestFile: path.resolve(c.packageRoot, selected.file),\n };\n}\nfunction remove(raw: Record<string, unknown>, keys: readonly string[]): void {\n let current = raw;\n const parents: Array<[Record<string, unknown>, string]> = [];\n for (const key of keys.slice(0, -1)) {\n const next = current[key];\n if (!next || typeof next !== \"object\" || Array.isArray(next)) return;\n parents.push([current, key]);\n current = next as Record<string, unknown>;\n }\n delete current[keys.at(-1)!];\n for (const [parent, key] of parents.reverse()) {\n const value = parent[key];\n if (value && typeof value === \"object\" && !Object.keys(value).length) delete parent[key];\n else break;\n }\n}\nfunction projection(raw: Record<string, unknown>, d: ProcessGroupDirectDescriptor, excluded: readonly string[]) {\n const copy = structuredClone(raw);\n remove(copy, d.journalPath);\n remove(copy, d.runtimeRolePath);\n for (const r of d.resources) if (r.kind === \"file\") remove(copy, r.manifestPath);\n const uns = copy[\"uns\"];\n if (uns && typeof uns === \"object\" && !Array.isArray(uns)) for (const key of excluded) delete (uns as Record<string, unknown>)[key];\n // Removing a lifecycle leaf must not turn an otherwise empty publisher into a difference.\n const publisher = readConfigurationSelector(copy, d.publisherPath);\n if (publisher && typeof publisher === \"object\" && !Object.keys(publisher).length) remove(copy, d.publisherPath);\n return hash(copy);\n}\n/** Data-only installed-resource review. Does not stop, initialize, rewrite or grant launch authority. */\nexport function reviewInstalledProcessGroupDirectTransition(\n operationId: string,\n rawInput: unknown,\n configs: DirectTransitionConfigurations,\n stateRoot: string,\n excludedUnsFields: readonly string[] = [],\n) {\n const input = processGroupDirectInputSchema.parse(rawInput),\n owner = input.target.controller,\n first = configs.source.publisher,\n target = configs.target;\n const pkg = (c: Config) => JSON.parse(read(path.join(c.packageRoot, \"package.json\")).toString());\n for (const [p, c] of [\n [input.source.publisher, first],\n [input.source.receiver, configs.source.receiver],\n [input.target, target],\n ] as const) {\n if (\n path.resolve(c.packageRoot, \"instances\", p.instanceId) !== c.instanceDirectory ||\n fs.realpathSync(c.instanceDirectory) !== c.instanceDirectory ||\n pkg(c).name !== p.rttNode ||\n pkg(c).version !== p.version\n )\n throw Error(\"Exact installed package and instance placement required\");\n }\n const context = (c: Config) => ({\n packageRoot: c.packageRoot,\n instanceDirectory: c.instanceDirectory,\n rawConfiguration: c.raw,\n channels: resolvedProcessGroupChannels(c.resolved),\n controllerName: owner,\n stateRoot,\n });\n const old = authorizeProcessGroupRuntime(context(first)),\n receiver = authorizeProcessGroupRuntime(context(configs.source.receiver));\n if (\n old.role !== \"target\" ||\n receiver.role !== \"receiver\" ||\n old.file !== receiver.file ||\n old.sha256 !== receiver.sha256 ||\n old.directory !== receiver.directory ||\n !old.journalId ||\n old.journalId !== receiver.journalId\n )\n throw Error(\"Exact authorized publisher/receiver owners required\");\n const sourcePolicy = read(old.file, true),\n sourceDescriptor = selectedProcessGroupDescriptor(first.packageRoot, first.raw);\n if (!sourceDescriptor) throw Error(\"Missing source shared contract\");\n const normalized = normalizeRuntimeProcessGroup(first.raw, sourceDescriptor),\n direct = describeDirectProcessGroup(target),\n d = direct.descriptor;\n const namespace = sourceDescriptor.namespace;\n if (\n d.namespace !== namespace ||\n hash(d.publisherPath) !== hash(sourceDescriptor.publisherPath) ||\n hash(d.journalPath) !== hash(sourceDescriptor.journalPath) ||\n hash(d.runtimeRolePath) !== hash(sourceDescriptor.runtimeRolePath) ||\n direct.groupId !== old.groupId ||\n direct.processName !== old.groupProcessName ||\n (target.raw[\"uns\"] as Record<string, unknown>)?.[\"processName\"] !== old.groupProcessName ||\n projection(first.raw, d, excludedUnsFields) !== projection(target.raw, d, excludedUnsFields)\n )\n throw Error(\"Direct business configuration, selector or group identity changed\");\n const channels = groupChannelsHash(context(first).channels);\n if (channels !== groupChannelsHash(context(configs.source.receiver).channels) || channels !== groupChannelsHash(context(target).channels))\n throw Error(\"Direct broker/channel identity changed\");\n for (const c of [first, configs.source.receiver, target])\n if ((resolvedProcessGroupChannels(c.resolved)[2] as { publishQueue?: { enabled?: boolean } }).publishQueue?.enabled === true)\n throw Error(\"Initial direct retirement requires disabled disk MQTT output\");\n let reference, sourceResourceSha256: string;\n if (sourceDescriptor.protocolVersion === 2) {\n if (direct.resource.kind !== \"configuration\" || !direct.snapshot) throw Error(\"Resource kind must remain configuration based\");\n const generation = describeInstalledProcessGroupGeneration(first);\n reference = generation.reference;\n sourceResourceSha256 = configurationGroupSnapshot(readConfigurationSelector(first.raw, sourceDescriptor.groupPath)).sha256;\n } else {\n if (direct.resource.kind !== \"file\" || !direct.manifest) throw Error(\"Resource kind must remain file based\");\n const journal = processGroupJournalSchema.parse(normalized.journal);\n const declared = sourceDescriptor.manifests.find((m) => m.file === journal.groupManifest);\n if (!declared) throw Error(\"Unregistered original manifest\");\n const bytes = inside(first.packageRoot, declared.file),\n manifest = processGroupManifestSchema.parse(JSON.parse(bytes.toString()));\n sourceResourceSha256 = sha256(bytes);\n const contract = processGroupJournalContract(processGroupSourceIdentity(context(first).channels[1] as never), journal, manifest.profiles);\n reference = {\n directory: old.directory,\n journalId: old.journalId,\n journalContractSha256: sha256(contract),\n generationId: manifest.id,\n contractVersion: 1 as const,\n maxRecords: journal.maxRecords,\n maxBytes: journal.maxBytes,\n minFreeBytes: journal.minFreeBytes,\n profiles: manifest.profiles.map(({ processName, mappingSha256, dataGroup }) => ({ processName, mappingSha256, dataGroup })),\n };\n }\n const journal = retiredJournalReferenceSchema.parse(reference) as GenerationJournalReference;\n if (sourceResourceSha256 !== direct.resourceSha256 || hash(journal.profiles) !== hash(direct.profiles))\n throw Error(\"Direct profile resources, paths or units changed\");\n const usage = inspectGenerationJournal(journal); // Pending work is allowed at preview, never at policy switch.\n if (!Buffer.from(sourcePolicy.toString(), \"utf8\").equals(sourcePolicy)) throw Error(\"Original policy encoding cannot be retained exactly\");\n const member = (placement: typeof input.target, c: Config) => ({\n placement,\n processName: String((c.raw[\"uns\"] as Record<string, unknown>)[\"processName\"]),\n configurationSha256: hash(c.raw),\n artifactSha256: groupArtifactHash(c.packageRoot),\n });\n const policy = processGroupRetirementPolicySchema.parse({\n schemaVersion: 5,\n kind: \"uns-process-group-direct-retirement\",\n protocolVersion: 1,\n operationId,\n packageName: pkg(first).name,\n namespace,\n groupId: old.groupId,\n controllerName: owner,\n stateRoot,\n recovery: \"open\",\n journal,\n sourcePolicyJson: sourcePolicy.toString(),\n sourcePolicySha256: sha256(sourcePolicy),\n source: {\n publisher: {\n ...member(input.source.publisher, first),\n policyConfigurationSha256: sourceDescriptor.protocolVersion === 2 ? configurationResourceHash(first.raw) : hash(first.raw),\n },\n receiver: {\n ...member(input.source.receiver, configs.source.receiver),\n policyConfigurationSha256:\n sourceDescriptor.protocolVersion === 2 ? configurationResourceHash(configs.source.receiver.raw) : hash(configs.source.receiver.raw),\n },\n },\n target: {\n ...member(input.target, target),\n packageRoot: target.packageRoot,\n descriptorSha256: hash(d),\n resourceSha256: direct.resourceSha256,\n channelsSha256: channels,\n },\n });\n if (sha256(read(old.file, true)) !== policy.sourcePolicySha256) throw Error(\"Original policy changed during direct review\");\n const targetPolicy = Buffer.from(JSON.stringify(policy));\n if (targetPolicy.length > 65536) throw Error(\"Retirement policy byte budget exceeded\");\n return {\n review: {\n protocolVersion: 1 as const,\n kind: \"paired-to-direct\" as const,\n input,\n operationId,\n policyFile: old.file,\n sourcePolicySha256: sha256(sourcePolicy),\n targetPolicySha256: sha256(targetPolicy),\n journal,\n source: policy.source,\n target: policy.target,\n namespace,\n groupId: old.groupId,\n delivery: { inputPausePossible: true, exactlyOnceOutput: false, brokerReplayNotTransferred: true },\n usage,\n },\n sourcePolicy,\n targetPolicy,\n };\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import type { UpgradeConfiguration } from "./process-group-upgrade.js";
2
+ export type DirectRuntimeContext = UpgradeConfiguration & {
3
+ controllerName: string;
4
+ operationId?: string;
5
+ launchId?: string;
6
+ };
7
+ /** Startup guard, shared by host and application. An installed declaration never grants authority. */
8
+ export declare function assertProcessGroupDirectLaunch(context: DirectRuntimeContext): void;
9
+ /** PID/launch-bound observation, never authority. Start after output confirmation and input handler setup. */
10
+ export declare function trackProcessGroupDirectReadiness(context: DirectRuntimeContext, ready: () => boolean): () => void;
11
+ export declare function inspectProcessGroupDirectReadiness(directory: string, expected: {
12
+ pid: number;
13
+ launchId: string;
14
+ configurationSha256: string;
15
+ }, now?: number): boolean;
16
+ /** Preserve the managed registry in a direct process; never inherit a journal-mode launch permit. */
17
+ export declare function processGroupDirectLaunchEnvironment(operationId: string | undefined): Record<string, string>;
18
+ //# sourceMappingURL=process-group-direct-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-direct-runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-direct-runtime.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GAAG;IACxD,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,sGAAsG;AACtG,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CA4ElF;AAED,8GAA8G;AAC9G,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,OAAO,GAAG,MAAM,IAAI,CAgChH;AACD,wBAAgB,kCAAkC,CAChD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,EACxE,GAAG,SAAa,GACf,OAAO,CAuBT;AAED,qGAAqG;AACrG,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ3G"}
@@ -0,0 +1,154 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { configuredGroupProcessNames, hasProcessGroupAuthorization, parseProcessGroupRetirementPolicy } from "./process-group-authorization.js";
6
+ import { resolvedProcessGroupChannels } from "./process-group-contract.js";
7
+ import { describeDirectProcessGroup, processGroupDirectDescriptor } from "./process-group-direct-review.js";
8
+ import { inspectGenerationJournal } from "./process-group-generation.js";
9
+ import { groupArtifactHash, groupChannelsHash, configurationAuthorizationHash as hash, assertPrivateProcessGroupDirectory as privateDirectory, readProcessGroupResource as read, } from "./process-group-resources.js";
10
+ /** Startup guard, shared by host and application. An installed declaration never grants authority. */
11
+ export function assertProcessGroupDirectLaunch(context) {
12
+ if (!hasProcessGroupAuthorization())
13
+ return; // Standalone deployments without a managed journal remain supported.
14
+ const names = configuredGroupProcessNames(), name = String(context.raw["uns"]?.["processName"]);
15
+ if (!names.has(name))
16
+ return;
17
+ const d = processGroupDirectDescriptor(context.packageRoot);
18
+ if (!d)
19
+ throw Error("Retained group identity requires a reviewed direct runtime");
20
+ const root = process.env["UNS_PROCESS_GROUP_STATE_ROOT"];
21
+ const directory = process.env["UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY"];
22
+ const single = process.env["UNS_PROCESS_GROUP_AUTHORIZATION_FILE"];
23
+ const registry = path.join(root, d.namespace, "authorizations");
24
+ privateDirectory(root);
25
+ privateDirectory(registry);
26
+ if (directory && directory !== root && directory !== registry)
27
+ throw Error("Foreign direct policy registry");
28
+ const files = new Set();
29
+ if (single)
30
+ files.add(single);
31
+ if (directory) {
32
+ const entries = fs.readdirSync(registry, { withFileTypes: true });
33
+ if (entries.length > 64)
34
+ throw Error("Direct policy budget exceeded");
35
+ for (const e of entries)
36
+ if (e.name.endsWith(".json"))
37
+ files.add(path.join(registry, e.name));
38
+ }
39
+ const policies = [...files]
40
+ .map((file) => ({ file, raw: JSON.parse(read(file, true).toString()) }))
41
+ .filter((p) => p.raw.schemaVersion === 5 && p.raw.target?.processName === name);
42
+ if (policies.length !== 1)
43
+ throw Error("Group input owners remain active or retired; reviewed direct authority required");
44
+ const { file, raw } = policies[0], p = parseProcessGroupRetirementPolicy(raw), actual = describeDirectProcessGroup(context), channels = resolvedProcessGroupChannels(context.resolved), pkg = JSON.parse(read(path.join(context.packageRoot, "package.json")).toString());
45
+ if (p.stateRoot !== root ||
46
+ p.namespace !== d.namespace ||
47
+ file !== path.join(registry, p.journal.generationId + ".json") ||
48
+ context.controllerName !== p.controllerName ||
49
+ pkg.name !== p.packageName ||
50
+ actual.groupId !== p.groupId ||
51
+ actual.processName !== name ||
52
+ actual.resourceSha256 !== p.target.resourceSha256 ||
53
+ hash(actual.profiles) !== hash(p.journal.profiles))
54
+ throw Error("Retained direct group resource or identity changed");
55
+ if (path.resolve(context.packageRoot) !== context.packageRoot ||
56
+ fs.realpathSync(context.packageRoot) !== context.packageRoot ||
57
+ path.dirname(context.instanceDirectory) !== path.join(context.packageRoot, "instances") ||
58
+ fs.realpathSync(context.instanceDirectory) !== context.instanceDirectory ||
59
+ !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(path.basename(context.instanceDirectory)))
60
+ throw Error("Canonical installed direct instance required");
61
+ const usage = inspectGenerationJournal(p.journal);
62
+ if (usage.records || usage.bytes)
63
+ throw Error("Retained input journal is not empty; direct launch blocked");
64
+ if (p.recovery === "closed")
65
+ return; // Original/profile and journal-mode launches remain fenced by schema5.
66
+ if (context.packageRoot !== p.target.packageRoot ||
67
+ pkg.version !== p.target.placement.version ||
68
+ context.instanceDirectory !== path.join(context.packageRoot, "instances", p.target.placement.instanceId) ||
69
+ fs.realpathSync(context.instanceDirectory) !== context.instanceDirectory ||
70
+ hash(context.raw) !== p.target.configurationSha256 ||
71
+ groupArtifactHash(context.packageRoot) !== p.target.artifactSha256 ||
72
+ hash(d) !== p.target.descriptorSha256 ||
73
+ groupChannelsHash(channels) !== p.target.channelsSha256 ||
74
+ channels[2].publishQueue?.enabled === true)
75
+ throw Error("Exact reviewed direct placement, configuration and artifact required");
76
+ const r = JSON.parse(read(path.join(context.instanceDirectory, "process-group-reservation.json"), true).toString());
77
+ if (!z.string().uuid().safeParse(context.launchId).success ||
78
+ context.operationId !== p.operationId ||
79
+ r.operationId !== p.operationId ||
80
+ r.role !== "target" ||
81
+ r.configurationChecksum !== p.target.configurationSha256 ||
82
+ r.lastLaunch?.launchId !== context.launchId ||
83
+ !z.string().uuid().safeParse(r.lastLaunch?.requestId).success)
84
+ throw Error("Direct target requires its exact reviewed launch reservation");
85
+ }
86
+ /** PID/launch-bound observation, never authority. Start after output confirmation and input handler setup. */
87
+ export function trackProcessGroupDirectReadiness(context, ready) {
88
+ assertProcessGroupDirectLaunch(context);
89
+ if (!context.launchId)
90
+ return () => { };
91
+ const file = path.join(context.instanceDirectory, "process-group-direct-readiness.json");
92
+ let active = true;
93
+ const publish = () => {
94
+ const bytes = JSON.stringify({
95
+ protocolVersion: 1,
96
+ pid: process.pid,
97
+ launchId: context.launchId,
98
+ configurationSha256: hash(context.raw),
99
+ ready: active && ready(),
100
+ at: Date.now(),
101
+ });
102
+ const temp = file + "." + randomUUID() + ".tmp", fd = fs.openSync(temp, "wx", 0o600);
103
+ try {
104
+ fs.writeFileSync(fd, bytes);
105
+ fs.fsyncSync(fd);
106
+ }
107
+ finally {
108
+ fs.closeSync(fd);
109
+ }
110
+ fs.renameSync(temp, file);
111
+ };
112
+ publish();
113
+ const timer = setInterval(publish, 1000);
114
+ timer.unref();
115
+ return () => {
116
+ active = false;
117
+ clearInterval(timer);
118
+ publish();
119
+ };
120
+ }
121
+ export function inspectProcessGroupDirectReadiness(directory, expected, now = Date.now()) {
122
+ try {
123
+ const r = z
124
+ .strictObject({
125
+ protocolVersion: z.literal(1),
126
+ pid: z.number().int().positive(),
127
+ launchId: z.string().uuid(),
128
+ configurationSha256: z.string().regex(/^[a-f0-9]{64}$/),
129
+ ready: z.boolean(),
130
+ at: z.number().int().positive(),
131
+ })
132
+ .parse(JSON.parse(read(path.join(directory, "process-group-direct-readiness.json"), true).toString()));
133
+ return (r.ready &&
134
+ r.pid === expected.pid &&
135
+ r.launchId === expected.launchId &&
136
+ r.configurationSha256 === expected.configurationSha256 &&
137
+ r.at <= now + 1000 &&
138
+ now - r.at <= 5000);
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ /** Preserve the managed registry in a direct process; never inherit a journal-mode launch permit. */
145
+ export function processGroupDirectLaunchEnvironment(operationId) {
146
+ return {
147
+ UNS_PROCESS_GROUP_LOCAL_PILOT: "0",
148
+ UNS_PROCESS_GROUP_AUTHORIZATION_FILE: process.env["UNS_PROCESS_GROUP_AUTHORIZATION_FILE"] ?? "",
149
+ UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY: process.env["UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY"] ?? "",
150
+ UNS_PROCESS_GROUP_STATE_ROOT: process.env["UNS_PROCESS_GROUP_STATE_ROOT"] ?? "",
151
+ UNS_PROCESS_GROUP_OPERATION_ID: operationId ?? "",
152
+ };
153
+ }
154
+ //# sourceMappingURL=process-group-direct-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-direct-runtime.js","sourceRoot":"","sources":["../../src/runtime/process-group-direct-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\n\nimport { configuredGroupProcessNames, hasProcessGroupAuthorization, parseProcessGroupRetirementPolicy } from \"./process-group-authorization.js\";\nimport { resolvedProcessGroupChannels } from \"./process-group-contract.js\";\nimport { describeDirectProcessGroup, processGroupDirectDescriptor } from \"./process-group-direct-review.js\";\nimport { type GenerationJournalReference, inspectGenerationJournal } from \"./process-group-generation.js\";\nimport {\n groupArtifactHash,\n groupChannelsHash,\n configurationAuthorizationHash as hash,\n assertPrivateProcessGroupDirectory as privateDirectory,\n readProcessGroupResource as read,\n} from \"./process-group-resources.js\";\nimport type { UpgradeConfiguration } from \"./process-group-upgrade.js\";\n\nexport type DirectRuntimeContext = UpgradeConfiguration & {\n controllerName: string;\n operationId?: string;\n launchId?: string;\n};\n/** Startup guard, shared by host and application. An installed declaration never grants authority. */\nexport function assertProcessGroupDirectLaunch(context: DirectRuntimeContext): void {\n if (!hasProcessGroupAuthorization()) return; // Standalone deployments without a managed journal remain supported.\n const names = configuredGroupProcessNames(),\n name = String((context.raw[\"uns\"] as Record<string, unknown>)?.[\"processName\"]);\n if (!names.has(name)) return;\n const d = processGroupDirectDescriptor(context.packageRoot);\n if (!d) throw Error(\"Retained group identity requires a reviewed direct runtime\");\n const root = process.env[\"UNS_PROCESS_GROUP_STATE_ROOT\"]!;\n const directory = process.env[\"UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY\"];\n const single = process.env[\"UNS_PROCESS_GROUP_AUTHORIZATION_FILE\"];\n const registry = path.join(root, d.namespace, \"authorizations\");\n privateDirectory(root);\n privateDirectory(registry);\n if (directory && directory !== root && directory !== registry) throw Error(\"Foreign direct policy registry\");\n const files = new Set<string>();\n if (single) files.add(single);\n if (directory) {\n const entries = fs.readdirSync(registry, { withFileTypes: true });\n if (entries.length > 64) throw Error(\"Direct policy budget exceeded\");\n for (const e of entries) if (e.name.endsWith(\".json\")) files.add(path.join(registry, e.name));\n }\n const policies = [...files]\n .map((file) => ({ file, raw: JSON.parse(read(file, true).toString()) }))\n .filter((p) => p.raw.schemaVersion === 5 && p.raw.target?.processName === name);\n if (policies.length !== 1) throw Error(\"Group input owners remain active or retired; reviewed direct authority required\");\n const { file, raw } = policies[0]!,\n p = parseProcessGroupRetirementPolicy(raw),\n actual = describeDirectProcessGroup(context),\n channels = resolvedProcessGroupChannels(context.resolved),\n pkg = JSON.parse(read(path.join(context.packageRoot, \"package.json\")).toString());\n if (\n p.stateRoot !== root ||\n p.namespace !== d.namespace ||\n file !== path.join(registry, p.journal.generationId + \".json\") ||\n context.controllerName !== p.controllerName ||\n pkg.name !== p.packageName ||\n actual.groupId !== p.groupId ||\n actual.processName !== name ||\n actual.resourceSha256 !== p.target.resourceSha256 ||\n hash(actual.profiles) !== hash(p.journal.profiles)\n )\n throw Error(\"Retained direct group resource or identity changed\");\n if (\n path.resolve(context.packageRoot) !== context.packageRoot ||\n fs.realpathSync(context.packageRoot) !== context.packageRoot ||\n path.dirname(context.instanceDirectory) !== path.join(context.packageRoot, \"instances\") ||\n fs.realpathSync(context.instanceDirectory) !== context.instanceDirectory ||\n !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(path.basename(context.instanceDirectory))\n )\n throw Error(\"Canonical installed direct instance required\");\n const usage = inspectGenerationJournal(p.journal as GenerationJournalReference);\n if (usage.records || usage.bytes) throw Error(\"Retained input journal is not empty; direct launch blocked\");\n if (p.recovery === \"closed\") return; // Original/profile and journal-mode launches remain fenced by schema5.\n if (\n context.packageRoot !== p.target.packageRoot ||\n pkg.version !== p.target.placement.version ||\n context.instanceDirectory !== path.join(context.packageRoot, \"instances\", p.target.placement.instanceId) ||\n fs.realpathSync(context.instanceDirectory) !== context.instanceDirectory ||\n hash(context.raw) !== p.target.configurationSha256 ||\n groupArtifactHash(context.packageRoot) !== p.target.artifactSha256 ||\n hash(d) !== p.target.descriptorSha256 ||\n groupChannelsHash(channels) !== p.target.channelsSha256 ||\n (channels[2] as { publishQueue?: { enabled?: boolean } }).publishQueue?.enabled === true\n )\n throw Error(\"Exact reviewed direct placement, configuration and artifact required\");\n const r = JSON.parse(read(path.join(context.instanceDirectory, \"process-group-reservation.json\"), true).toString());\n if (\n !z.string().uuid().safeParse(context.launchId).success ||\n context.operationId !== p.operationId ||\n r.operationId !== p.operationId ||\n r.role !== \"target\" ||\n r.configurationChecksum !== p.target.configurationSha256 ||\n r.lastLaunch?.launchId !== context.launchId ||\n !z.string().uuid().safeParse(r.lastLaunch?.requestId).success\n )\n throw Error(\"Direct target requires its exact reviewed launch reservation\");\n}\n\n/** PID/launch-bound observation, never authority. Start after output confirmation and input handler setup. */\nexport function trackProcessGroupDirectReadiness(context: DirectRuntimeContext, ready: () => boolean): () => void {\n assertProcessGroupDirectLaunch(context);\n if (!context.launchId) return () => {};\n const file = path.join(context.instanceDirectory, \"process-group-direct-readiness.json\");\n let active = true;\n const publish = () => {\n const bytes = JSON.stringify({\n protocolVersion: 1,\n pid: process.pid,\n launchId: context.launchId,\n configurationSha256: hash(context.raw),\n ready: active && ready(),\n at: Date.now(),\n });\n const temp = file + \".\" + randomUUID() + \".tmp\",\n fd = fs.openSync(temp, \"wx\", 0o600);\n try {\n fs.writeFileSync(fd, bytes);\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n fs.renameSync(temp, file);\n };\n publish();\n const timer = setInterval(publish, 1000);\n timer.unref();\n return () => {\n active = false;\n clearInterval(timer);\n publish();\n };\n}\nexport function inspectProcessGroupDirectReadiness(\n directory: string,\n expected: { pid: number; launchId: string; configurationSha256: string },\n now = Date.now(),\n): boolean {\n try {\n const r = z\n .strictObject({\n protocolVersion: z.literal(1),\n pid: z.number().int().positive(),\n launchId: z.string().uuid(),\n configurationSha256: z.string().regex(/^[a-f0-9]{64}$/),\n ready: z.boolean(),\n at: z.number().int().positive(),\n })\n .parse(JSON.parse(read(path.join(directory, \"process-group-direct-readiness.json\"), true).toString()));\n return (\n r.ready &&\n r.pid === expected.pid &&\n r.launchId === expected.launchId &&\n r.configurationSha256 === expected.configurationSha256 &&\n r.at <= now + 1000 &&\n now - r.at <= 5000\n );\n } catch {\n return false;\n }\n}\n\n/** Preserve the managed registry in a direct process; never inherit a journal-mode launch permit. */\nexport function processGroupDirectLaunchEnvironment(operationId: string | undefined): Record<string, string> {\n return {\n UNS_PROCESS_GROUP_LOCAL_PILOT: \"0\",\n UNS_PROCESS_GROUP_AUTHORIZATION_FILE: process.env[\"UNS_PROCESS_GROUP_AUTHORIZATION_FILE\"] ?? \"\",\n UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY: process.env[\"UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY\"] ?? \"\",\n UNS_PROCESS_GROUP_STATE_ROOT: process.env[\"UNS_PROCESS_GROUP_STATE_ROOT\"] ?? \"\",\n UNS_PROCESS_GROUP_OPERATION_ID: operationId ?? \"\",\n };\n}\n"]}
@@ -79,6 +79,7 @@ const namespaces = rootEntries
79
79
  .sort();
80
80
  if (namespaces.length > 64) fail();
81
81
  const capturedGroups = new Set();
82
+ const retirementChecks = new Map();
82
83
  for (const namespace of namespaces) {
83
84
  if (!/^[a-z][a-z0-9-]{0,99}$/.test(namespace)) fail();
84
85
  const namespaceRoot = path.join(root, namespace),
@@ -240,9 +241,52 @@ for (const namespace of namespaces) {
240
241
  if (snapshotBytes > limits.maximumSnapshotBytes) fail();
241
242
  info[name === "admission.sqlite" ? "admissionSha256" : "ownershipSha256"] = fileHash(p);
242
243
  }
244
+ // Retired ownership is part of recovery evidence, never an automatic launch permit.
245
+ // Version2 makes an older transport fail closed instead of silently omitting it.
246
+ const policyDirectory=path.join(namespaceRoot,"authorizations"),policyFile=path.join(policyDirectory,group+".json");
247
+ let policyExists=false;
248
+ try{fs.lstatSync(policyFile);policyExists=true;}catch(e){if(e.code!=="ENOENT")throw e;}
249
+ if(policyExists){
250
+ check(policyDirectory,true);check(policyFile);
251
+ if(fs.statSync(policyFile).size>65536)fail();
252
+ const policy=fs.readFileSync(policyFile),p=JSON.parse(policy.toString());
253
+ if(p.schemaVersion===5){
254
+ if(info.usage.records!==0||info.usage.bytes!==0||p.kind!=="uns-process-group-direct-retirement"||p.protocolVersion!==1||p.stateRoot!==root||p.namespace!==namespace||
255
+ p.journal?.directory!==source||p.journal?.generationId!==group||p.journal?.journalId!==info.journalId||
256
+ p.journal?.journalContractSha256!==info.contractSha256||typeof p.sourcePolicyJson!=="string"||Buffer.byteLength(p.sourcePolicyJson)>32768||hash(p.sourcePolicyJson)!==p.sourcePolicySha256||
257
+ !["open","closed"].includes(p.recovery))fail();
258
+ fs.writeFileSync(path.join(target,"retirement-policy.json"),policy,{mode:0o600,flag:"wx"});
259
+ info.retirementPolicySha256=hash(policy);info.retirementPolicyBytes=policy.length;
260
+ snapshotBytes+=policy.length;if(snapshotBytes>limits.maximumSnapshotBytes)fail();
261
+ // Freeze this observation; a concurrent policy switch requires a new consistent capture.
262
+ if(!fs.readFileSync(policyFile).equals(policy))fail();
263
+ manifest.schemaVersion=2;
264
+ retirementChecks.set(policyFile,hash(policy));
265
+ }
266
+ }
243
267
  manifest.groups.push(info);
244
268
  }
245
269
  }
270
+ // Direct configurations no longer name the old journal. Its retained policy must
271
+ // still resolve to captured state, even after the stopped source configs are removed.
272
+ let registryFiles=0;
273
+ for(const namespace of namespaces){
274
+ const registry=path.join(root,namespace,"authorizations");
275
+ let entries;
276
+ try{check(registry,true);entries=fs.readdirSync(registry,{withFileTypes:true});}catch(e){if(e.code==="ENOENT")continue;throw e;}
277
+ if(entries.length>64||entries.some(e=>e.isSymbolicLink()))fail();
278
+ for(const entry of entries){
279
+ if(!entry.name.endsWith(".json"))continue;
280
+ if(++registryFiles>64||!entry.isFile()||!/^([a-z][a-z0-9-]{0,99})\.json$/.test(entry.name))fail();
281
+ const file=path.join(registry,entry.name);check(file);if(fs.statSync(file).size>65536)fail();
282
+ const bytes=fs.readFileSync(file),policy=JSON.parse(bytes.toString());
283
+ if(policy.schemaVersion!==5)continue;
284
+ const captured=manifest.groups.find(g=>g.namespace===namespace&&g.group===policy.journal?.generationId);
285
+ if(!captured||captured.retirementPolicySha256!==hash(bytes)||captured.journalId!==policy.journal?.journalId||
286
+ policy.namespace!==namespace||policy.stateRoot!==root||entry.name!==policy.journal.generationId+".json")fail();
287
+ }
288
+ }
289
+ for(const [file,digest] of retirementChecks){check(file);if(hash(fs.readFileSync(file))!==digest)fail();}
246
290
  const remaining = fs.statfsSync(output, { bigint: true });
247
291
  if (remaining.bavail * remaining.bsize < BigInt(snapshotBytes + 64 * 1024 * 1024)) fail();
248
292
  const manifestBytes = JSON.stringify(manifest) + "\n";
@@ -1,3 +1,4 @@
1
+ import { type MqttDrainReceipt } from "../runtime/mqtt-drain.js";
1
2
  import UnsMqttProxy from "../uns-mqtt/uns-mqtt-proxy.js";
2
3
  import type { UnsMqttProxyStopOptions } from "../uns-mqtt/uns-mqtt-proxy.js";
3
4
  import { type UnsServiceMetadata, type UnsServiceMetadataInput } from "./service-metadata.js";
@@ -31,6 +32,8 @@ declare class UnsProxyProcess {
31
32
  private statusMonitor;
32
33
  private serviceMetadataTopic;
33
34
  private shutdownPromise;
35
+ private migrationDrainPromise;
36
+ private migrationDrainHandler?;
34
37
  static pluginApiVersion: number;
35
38
  private static registered;
36
39
  private static registeredMethodNames;
@@ -58,10 +61,11 @@ declare class UnsProxyProcess {
58
61
  * with live process status to decide whether a service is currently healthy.
59
62
  */
60
63
  publishServiceMetadata(metadata: UnsServiceMetadataInput): Promise<UnsServiceMetadata>;
61
- /**
62
- * Shuts down the process by clearing intervals, timeouts, and removing
63
- * MQTT event listeners, and stopping the StatusMonitor.
64
- */
64
+ /** Call after application input handlers and shutdown hooks are prepared. */
65
+ enableMigrationDrain(): void;
66
+ /** Works without a Controller too; success means confirmed empty output and closed owners. */
67
+ drainForMigration(timeoutMs?: number): Promise<MqttDrainReceipt>;
68
+ /** Stop process timers, status publication and all owned MQTT proxies. */
65
69
  shutdown(options?: UnsMqttProxyStopOptions): Promise<void>;
66
70
  private performShutdown;
67
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"uns-proxy-process.d.ts","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"AAMA,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAK7E,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,uBAAuB,EAA2B,MAAM,uBAAuB,CAAC;AAEvH,OAAO,EAAe,cAAc,EAAE,qBAAqB,EAAa,MAAM,qBAAqB,CAAC;AAGpG;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;AAEjG,MAAM,MAAM,4BAA4B,GAAG,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;AAEvF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,CAAC;IACpD,eAAe,EAAE,OAAO,eAAe,CAAC;CACzC;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,wBAAwB,KAAK,IAAI,CAAC;AAE5E,cAAM,eAAe;IACnB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,gBAAgB,CAAoC;IAC5D,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,eAAe,CAA8B;IAGrD,MAAM,CAAC,gBAAgB,SAAK;IAC5B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAoC;IAC7D,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAqB;IACzD,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAE/B,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,qBAAqB;IAOxC,OAAO,CAAC,MAAM,CAAC,WAAW;IA0B1B,OAAO,CAAC,MAAM,CAAC,QAAQ;IAOvB,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,QAAQ,EAAE,MAAM,EAAE,yBAAyB,EAAE,qBAAqB;IA0E9E;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;OAEG;IACU,kBAAkB,CAC7B,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,cAAc,GAC7B,OAAO,CAAC,YAAY,CAAC;IAwCX,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtD;;;;;;OAMG;IACU,sBAAsB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAWnG;;;OAGG;IACI,QAAQ,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,IAAI,CAAC;YASvD,eAAe;CAgD9B;AAED,UAAU,eAAe;CAAG;AAE5B,eAAe,eAAe,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"uns-proxy-process.d.ts","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { MQTT_DRAIN_HANDLER, MQTT_DRAIN_READY_EVENT, drainMqttForMigration } from "../runtime/mqtt-drain.js";
1
2
  import { randomBytes } from "crypto";
2
3
  import logger from "../logger.js";
3
4
  import MqttProxy from "../uns-mqtt/mqtt-proxy.js";
@@ -24,6 +25,8 @@ class UnsProxyProcess {
24
25
  statusMonitor;
25
26
  serviceMetadataTopic;
26
27
  shutdownPromise = null;
28
+ migrationDrainPromise = null;
29
+ migrationDrainHandler;
27
30
  // Plugin
28
31
  static pluginApiVersion = 1;
29
32
  static registered = new Set();
@@ -149,7 +152,7 @@ class UnsProxyProcess {
149
152
  * Creates a new UNS proxy instance and stores it for future management.
150
153
  */
151
154
  async createUnsMqttProxy(mqttHost, instanceName, instanceMode, handover, unsParameters) {
152
- if (unsParameters?.publishQueue && handover) {
155
+ if (unsParameters?.publishQueue && unsParameters.publishQueue.enabled !== false && handover) {
153
156
  throw new Error("Persistent MQTT output requires handover=false and one owner; legacy RAM handover does not transfer an outbox");
154
157
  }
155
158
  // Wait until the MQTT connection is established before proceeding.
@@ -200,10 +203,37 @@ class UnsProxyProcess {
200
203
  await this.processMqttProxy.publish(this.serviceMetadataTopic, JSON.stringify(resolved), { retain: true });
201
204
  return resolved;
202
205
  }
203
- /**
204
- * Shuts down the process by clearing intervals, timeouts, and removing
205
- * MQTT event listeners, and stopping the StatusMonitor.
206
- */
206
+ /** Call after application input handlers and shutdown hooks are prepared. */
207
+ enableMigrationDrain() {
208
+ const registry = globalThis;
209
+ if (this.migrationDrainHandler)
210
+ return;
211
+ if (registry[MQTT_DRAIN_HANDLER])
212
+ throw Error("One migration drain owner is allowed per process");
213
+ this.migrationDrainHandler = () => this.drainForMigration();
214
+ registry[MQTT_DRAIN_HANDLER] = this.migrationDrainHandler;
215
+ process.emit(MQTT_DRAIN_READY_EVENT, { protocol: 1 });
216
+ }
217
+ /** Works without a Controller too; success means confirmed empty output and closed owners. */
218
+ drainForMigration(timeoutMs = this.handoverShutdown?.timeoutMs ?? 30_000) {
219
+ if (this.migrationDrainPromise)
220
+ return this.migrationDrainPromise;
221
+ this.migrationDrainPromise = (async () => {
222
+ const receipt = await drainMqttForMigration({
223
+ quiesce: async () => {
224
+ this.handoverShutdown?.onRelease?.();
225
+ await Promise.all(this.unsMqttProxies.map(proxy => proxy.setSubscriberPassiveAndDrainQueue()));
226
+ },
227
+ finishAccepted: async () => { await this.handoverShutdown?.drain(); },
228
+ outputs: this.unsMqttProxies,
229
+ timeoutMs,
230
+ });
231
+ await this.shutdown({ drain: true, timeoutMs });
232
+ return receipt;
233
+ })().catch(error => { this.migrationDrainPromise = null; throw error; });
234
+ return this.migrationDrainPromise;
235
+ }
236
+ /** Stop process timers, status publication and all owned MQTT proxies. */
207
237
  shutdown(options = {}) {
208
238
  if (this.shutdownPromise) {
209
239
  return this.shutdownPromise;
@@ -254,6 +284,12 @@ class UnsProxyProcess {
254
284
  if (shutdownErrors.length > 0) {
255
285
  throw new AggregateError(shutdownErrors, `${this.processName} - Shutdown completed with errors.`);
256
286
  }
287
+ if (this.migrationDrainHandler) {
288
+ const registry = globalThis;
289
+ if (registry[MQTT_DRAIN_HANDLER] === this.migrationDrainHandler)
290
+ delete registry[MQTT_DRAIN_HANDLER];
291
+ process.channel?.unref();
292
+ }
257
293
  logger.info(`${this.processName} - Shutdown complete.`);
258
294
  }
259
295
  }
@@ -1 +1 @@
1
- {"version":3,"file":"uns-proxy-process.js","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"crypto\";\n\nimport logger from \"../logger.js\";\nimport { IMqttParameters } from \"../uns-mqtt/mqtt-interfaces.js\";\nimport MqttProxy from \"../uns-mqtt/mqtt-proxy.js\";\nimport { MqttTopicBuilder } from \"../uns-mqtt/mqtt-topic-builder.js\";\nimport UnsMqttProxy from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport type { UnsMqttProxyStopOptions } from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport { HandoverManager } from \"./handover-manager.js\";\nimport { validateHandoverShutdown, type HandoverShutdownHooks } from \"./handover-shutdown.js\";\n// Import configuration and initialization modules.\nimport { MQTT_UPDATE_INTERVAL, PACKAGE_INFO } from \"./process-config.js\";\nimport { type UnsServiceMetadata, type UnsServiceMetadataInput, buildUnsServiceMetadata } from \"./service-metadata.js\";\nimport { StatusMonitor } from \"./status-monitor.js\";\nimport { IUnsMessage, IUnsParameters, IUnsProcessParameters, UnsEvents } from \"./uns-interfaces.js\";\nimport { UnsPacket } from \"./uns-packet.js\";\n\n/**\n * UnsProxyProcess is responsible for managing the process lifecycle,\n * configuring MQTT (subscriptions and publishing for status updates), and\n * handling UNS proxy instances.\n *\n * It leverages HandoverManager for handover events and StatusMonitor for health reporting.\n */\nexport type UnsProxyProcessPluginMethod = (this: UnsProxyProcess, ...args: unknown[]) => unknown;\n\nexport type UnsProxyProcessPluginMethods = Record<string, UnsProxyProcessPluginMethod>;\n\nexport interface UnsProxyProcessPluginApi {\n version: number;\n define(methods: UnsProxyProcessPluginMethods): void;\n UnsProxyProcess: typeof UnsProxyProcess;\n}\n\nexport type UnsProxyProcessPlugin = (api: UnsProxyProcessPluginApi) => void;\n\nclass UnsProxyProcess {\n private active: boolean = false;\n private processStatusTopic: string;\n private processName: string;\n private processId: string;\n private handoverId: string | undefined;\n private handoverShutdown: HandoverShutdownHooks | undefined;\n private unsMqttProxies: UnsMqttProxy[];\n private unsApiProxies: unknown[];\n private processMqttProxy: MqttProxy;\n private handoverManager: HandoverManager;\n private statusMonitor: StatusMonitor;\n private serviceMetadataTopic: string;\n private shutdownPromise: Promise<void> | null = null;\n\n // Plugin\n static pluginApiVersion = 1;\n private static registered = new Set<UnsProxyProcessPlugin>();\n private static registeredMethodNames = new Set<string>();\n private static applied = false;\n\n static use(plugin: UnsProxyProcessPlugin) {\n if (this.registered.has(plugin)) return this;\n this.registered.add(plugin);\n if (this.applied) this.applyPlugin(plugin);\n return this;\n }\n\n private static applyPlugin(plugin: UnsProxyProcessPlugin) {\n const define: UnsProxyProcessPluginApi[\"define\"] = (methods) => {\n for (const [name, fn] of Object.entries(methods)) {\n if (typeof fn !== \"function\") {\n throw new TypeError(`UnsProxyProcess plugin attempted to register non-function member \\\"${name}\\\".`);\n }\n if (this.registeredMethodNames.has(name) || Reflect.has(this.prototype, name)) {\n throw new Error(`UnsProxyProcess plugin attempted to overwrite existing member \\\"${name}\\\".`);\n }\n Object.defineProperty(this.prototype, name, {\n value: fn,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n this.registeredMethodNames.add(name);\n }\n };\n\n plugin({\n define,\n version: this.pluginApiVersion,\n UnsProxyProcess: this,\n });\n }\n\n private static applyAll() {\n if (this.applied) return;\n this.applied = true;\n for (const p of this.registered) this.applyPlugin(p);\n }\n\n // References for cleanup.\n private mqttInputHandler: (event: any) => void;\n\n constructor(mqttHost: string, unsProxyProcessParameters: IUnsProcessParameters) {\n (this.constructor as typeof UnsProxyProcess).applyAll(); // Activate all the plugins\n\n this.unsMqttProxies = [];\n this.unsApiProxies = [];\n if (!unsProxyProcessParameters?.processName) {\n throw new Error(\"UnsProxyProcess requires a processName in configuration.\");\n }\n validateHandoverShutdown(unsProxyProcessParameters.handoverShutdown);\n this.handoverShutdown = unsProxyProcessParameters.handoverShutdown\n ? { ...unsProxyProcessParameters.handoverShutdown } : undefined;\n this.processName = unsProxyProcessParameters.processName;\n this.processId = randomBytes(16).toString(\"hex\");\n this.handoverId = unsProxyProcessParameters.handoverId ?? process.env[\"UNS_HANDOVER_ID\"];\n const { name: packageName, version } = PACKAGE_INFO;\n\n // Instantiate the topic builder.\n const topicBuilder = new MqttTopicBuilder(\n `uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageName)}/${MqttTopicBuilder.sanitizeTopicPart(version)}/${MqttTopicBuilder.sanitizeTopicPart(this.processName)}/`,\n );\n\n // Generate topics.\n const processStatusTopic = topicBuilder.getProcessStatusTopic();\n const handoverTopic = topicBuilder.getHandoverTopic();\n const wildcardActiveTopic = topicBuilder.getWildcardActiveTopic();\n const serviceMetadataTopic = topicBuilder.getServiceMetadataTopic();\n\n this.processStatusTopic = processStatusTopic;\n this.serviceMetadataTopic = serviceMetadataTopic;\n\n // Configure MQTT topics for subscription.\n const mqttSubToTopics = unsProxyProcessParameters?.mqttSubToTopics ?? [wildcardActiveTopic, handoverTopic];\n const mqttParameters: IMqttParameters = {\n mqttSubToTopics,\n username: unsProxyProcessParameters?.username ?? \"\",\n password: unsProxyProcessParameters?.password ?? \"\",\n mqttSSL: unsProxyProcessParameters?.mqttSSL ?? false,\n statusTopic: this.processStatusTopic,\n clientId: unsProxyProcessParameters?.clientId ?? `${this.processName}-${this.processId}`,\n hosts: unsProxyProcessParameters?.hosts,\n servers: unsProxyProcessParameters?.servers,\n port: unsProxyProcessParameters?.port,\n protocol: unsProxyProcessParameters?.protocol,\n keepalive: unsProxyProcessParameters?.keepalive,\n clean: unsProxyProcessParameters?.clean,\n connectTimeout: unsProxyProcessParameters?.connectTimeout,\n reconnectPeriod: unsProxyProcessParameters?.reconnectPeriod,\n reconnectOnConnackError: unsProxyProcessParameters?.reconnectOnConnackError,\n resubscribe: unsProxyProcessParameters?.resubscribe,\n queueQoSZero: unsProxyProcessParameters?.queueQoSZero,\n rejectUnauthorized: unsProxyProcessParameters?.rejectUnauthorized ?? false,\n properties: unsProxyProcessParameters?.properties,\n ca: unsProxyProcessParameters?.ca,\n cert: unsProxyProcessParameters?.cert,\n key: unsProxyProcessParameters?.key,\n servername: unsProxyProcessParameters?.servername,\n };\n\n // Initialize MQTT proxy and start connection.\n this.processMqttProxy = new MqttProxy(mqttHost, this.processName, mqttParameters);\n this.processMqttProxy.start();\n\n // Instantiate and start the StatusMonitor for memory and status updates.\n this.statusMonitor = new StatusMonitor(\n this.processMqttProxy,\n this.processStatusTopic,\n () => this.active,\n MQTT_UPDATE_INTERVAL,\n MQTT_UPDATE_INTERVAL,\n { processName: this.processName, processId: this.processId },\n );\n this.statusMonitor.start();\n }\n\n /**\n * Initializes the HandoverManager instance and sets up event listeners for handover and MQTT input events.\n * Determines handover and force start modes based on process arguments.\n */\n private initHandoverManager(instanceMode: string, handover: boolean, handoverId?: string) {\n const handoverRequestEnabled = instanceMode == \"handover\" ? true : false;\n const forceStartEnabled = instanceMode == \"force\" ? true : false;\n\n this.handoverManager = new HandoverManager(\n this.processName,\n this.processId,\n this.processMqttProxy,\n this.unsMqttProxies,\n handoverRequestEnabled,\n handover ?? true,\n forceStartEnabled,\n handoverId,\n this.handoverShutdown,\n );\n\n // Listen for handover events.\n this.handoverManager.event.on(\"handoverManager\", (event) => {\n this.active = event.active;\n });\n\n // Delegate MQTT events to the HandoverManager.\n this.mqttInputHandler = async (event: UnsEvents[\"input\"]) => {\n await this.handoverManager.handleMqttMessage(event);\n };\n this.processMqttProxy.event.on(\"input\", this.mqttInputHandler);\n }\n\n /**\n * Creates a new UNS proxy instance and stores it for future management.\n */\n public async createUnsMqttProxy(\n mqttHost: string,\n instanceName: string,\n instanceMode: string,\n handover: boolean,\n unsParameters?: IUnsParameters,\n ): Promise<UnsMqttProxy> {\n if (unsParameters?.publishQueue && handover) {\n throw new Error(\"Persistent MQTT output requires handover=false and one owner; legacy RAM handover does not transfer an outbox\");\n }\n // Wait until the MQTT connection is established before proceeding.\n await this.waitForProcessConnection();\n\n // Currently handover manager can handle only mqtt events\n if (!this.handoverManager) {\n this.initHandoverManager(\n instanceMode,\n handover,\n this.handoverId,\n );\n }\n\n const resolvedUnsParameters: IUnsParameters = {\n ...(unsParameters ?? {}),\n clientId: unsParameters?.clientId ?? `${this.processName}-${instanceName}-${this.processId}`,\n };\n const unsMqttProxy = new UnsMqttProxy(mqttHost, this.processName, instanceName, resolvedUnsParameters);\n\n // Listen for UNS proxy producing topics and publish them via MQTT.\n unsMqttProxy.event.on(\"unsProxyProducedTopics\", (event) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(event.producedTopics));\n });\n\n // Listen for UNS proxy status events and publish them via MQTT.\n unsMqttProxy.event.on(\"mqttProxyStatus\", (event) => {\n const time = UnsPacket.formatToISO8601(new Date());\n const unsMessage: IUnsMessage = { data: { time, value: event.value, uom: event.uom } };\n UnsPacket.unsPacketFromUnsMessage(unsMessage).then((packet) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(packet));\n });\n });\n\n this.unsMqttProxies.push(unsMqttProxy);\n return unsMqttProxy;\n }\n\n public async waitForProcessConnection(): Promise<void> {\n while (!this.processMqttProxy?.isConnected) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n /**\n * Publishes retained product/system service metadata for controller discovery.\n *\n * The payload is intentionally separate from the volatile active/alive status\n * topics. Controllers can combine this retained identity/capability metadata\n * with live process status to decide whether a service is currently healthy.\n */\n public async publishServiceMetadata(metadata: UnsServiceMetadataInput): Promise<UnsServiceMetadata> {\n await this.waitForProcessConnection();\n const resolved = buildUnsServiceMetadata({\n processName: this.processName,\n processId: this.processId,\n metadata,\n });\n await this.processMqttProxy.publish(this.serviceMetadataTopic, JSON.stringify(resolved), { retain: true });\n return resolved;\n }\n\n /**\n * Shuts down the process by clearing intervals, timeouts, and removing\n * MQTT event listeners, and stopping the StatusMonitor.\n */\n public shutdown(options: UnsMqttProxyStopOptions = {}): Promise<void> {\n if (this.shutdownPromise) {\n return this.shutdownPromise;\n }\n\n this.shutdownPromise = this.performShutdown(options);\n return this.shutdownPromise;\n }\n\n private async performShutdown(options: UnsMqttProxyStopOptions): Promise<void> {\n logger.info(`${this.processName} - Shutting down UnsProxyProcess...`);\n const shutdownErrors: Error[] = [];\n\n try {\n this.statusMonitor.stop();\n await this.statusMonitor.publishInactiveStatus();\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping StatusMonitor or publishing passive state: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (this.mqttInputHandler) {\n try {\n this.processMqttProxy.event.off(\"input\", this.mqttInputHandler);\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error removing MQTT input handler: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n const proxyStopResults = await Promise.allSettled(this.unsMqttProxies.map((proxy) => proxy.stop(options)));\n for (const result of proxyStopResults) {\n if (result.status === \"rejected\") {\n const reason = result.reason instanceof Error ? result.reason : new Error(String(result.reason));\n logger.error(`${this.processName} - Error stopping UNS MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n try {\n if (typeof this.processMqttProxy.stop === \"function\") {\n await this.processMqttProxy.stop();\n }\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (shutdownErrors.length > 0) {\n throw new AggregateError(shutdownErrors, `${this.processName} - Shutdown completed with errors.`);\n }\n\n logger.info(`${this.processName} - Shutdown complete.`);\n }\n}\n\ninterface UnsProxyProcess {}\n\nexport default UnsProxyProcess;\nexport type { UnsServiceMetadata, UnsServiceMetadataInput };\nexport { UnsProxyProcess };\n"]}
1
+ {"version":3,"file":"uns-proxy-process.js","sourceRoot":"","sources":["../../src/uns/uns-proxy-process.ts"],"names":[],"mappings":"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","sourcesContent":["import { MQTT_DRAIN_HANDLER, MQTT_DRAIN_READY_EVENT, drainMqttForMigration, type MqttDrainReceipt } from \"../runtime/mqtt-drain.js\";\nimport { randomBytes } from \"crypto\";\n\nimport logger from \"../logger.js\";\nimport { IMqttParameters } from \"../uns-mqtt/mqtt-interfaces.js\";\nimport MqttProxy from \"../uns-mqtt/mqtt-proxy.js\";\nimport { MqttTopicBuilder } from \"../uns-mqtt/mqtt-topic-builder.js\";\nimport UnsMqttProxy from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport type { UnsMqttProxyStopOptions } from \"../uns-mqtt/uns-mqtt-proxy.js\";\nimport { HandoverManager } from \"./handover-manager.js\";\nimport { validateHandoverShutdown, type HandoverShutdownHooks } from \"./handover-shutdown.js\";\n// Import configuration and initialization modules.\nimport { MQTT_UPDATE_INTERVAL, PACKAGE_INFO } from \"./process-config.js\";\nimport { type UnsServiceMetadata, type UnsServiceMetadataInput, buildUnsServiceMetadata } from \"./service-metadata.js\";\nimport { StatusMonitor } from \"./status-monitor.js\";\nimport { IUnsMessage, IUnsParameters, IUnsProcessParameters, UnsEvents } from \"./uns-interfaces.js\";\nimport { UnsPacket } from \"./uns-packet.js\";\n\n/**\n * UnsProxyProcess is responsible for managing the process lifecycle,\n * configuring MQTT (subscriptions and publishing for status updates), and\n * handling UNS proxy instances.\n *\n * It leverages HandoverManager for handover events and StatusMonitor for health reporting.\n */\nexport type UnsProxyProcessPluginMethod = (this: UnsProxyProcess, ...args: unknown[]) => unknown;\n\nexport type UnsProxyProcessPluginMethods = Record<string, UnsProxyProcessPluginMethod>;\n\nexport interface UnsProxyProcessPluginApi {\n version: number;\n define(methods: UnsProxyProcessPluginMethods): void;\n UnsProxyProcess: typeof UnsProxyProcess;\n}\n\nexport type UnsProxyProcessPlugin = (api: UnsProxyProcessPluginApi) => void;\n\nclass UnsProxyProcess {\n private active: boolean = false;\n private processStatusTopic: string;\n private processName: string;\n private processId: string;\n private handoverId: string | undefined;\n private handoverShutdown: HandoverShutdownHooks | undefined;\n private unsMqttProxies: UnsMqttProxy[];\n private unsApiProxies: unknown[];\n private processMqttProxy: MqttProxy;\n private handoverManager: HandoverManager;\n private statusMonitor: StatusMonitor;\n private serviceMetadataTopic: string;\n private shutdownPromise: Promise<void> | null = null;\n private migrationDrainPromise: Promise<MqttDrainReceipt> | null = null;\n private migrationDrainHandler?: () => Promise<MqttDrainReceipt>;\n\n // Plugin\n static pluginApiVersion = 1;\n private static registered = new Set<UnsProxyProcessPlugin>();\n private static registeredMethodNames = new Set<string>();\n private static applied = false;\n\n static use(plugin: UnsProxyProcessPlugin) {\n if (this.registered.has(plugin)) return this;\n this.registered.add(plugin);\n if (this.applied) this.applyPlugin(plugin);\n return this;\n }\n\n private static applyPlugin(plugin: UnsProxyProcessPlugin) {\n const define: UnsProxyProcessPluginApi[\"define\"] = (methods) => {\n for (const [name, fn] of Object.entries(methods)) {\n if (typeof fn !== \"function\") {\n throw new TypeError(`UnsProxyProcess plugin attempted to register non-function member \\\"${name}\\\".`);\n }\n if (this.registeredMethodNames.has(name) || Reflect.has(this.prototype, name)) {\n throw new Error(`UnsProxyProcess plugin attempted to overwrite existing member \\\"${name}\\\".`);\n }\n Object.defineProperty(this.prototype, name, {\n value: fn,\n writable: true,\n configurable: true,\n enumerable: false,\n });\n this.registeredMethodNames.add(name);\n }\n };\n\n plugin({\n define,\n version: this.pluginApiVersion,\n UnsProxyProcess: this,\n });\n }\n\n private static applyAll() {\n if (this.applied) return;\n this.applied = true;\n for (const p of this.registered) this.applyPlugin(p);\n }\n\n // References for cleanup.\n private mqttInputHandler: (event: any) => void;\n\n constructor(mqttHost: string, unsProxyProcessParameters: IUnsProcessParameters) {\n (this.constructor as typeof UnsProxyProcess).applyAll(); // Activate all the plugins\n\n this.unsMqttProxies = [];\n this.unsApiProxies = [];\n if (!unsProxyProcessParameters?.processName) {\n throw new Error(\"UnsProxyProcess requires a processName in configuration.\");\n }\n validateHandoverShutdown(unsProxyProcessParameters.handoverShutdown);\n this.handoverShutdown = unsProxyProcessParameters.handoverShutdown\n ? { ...unsProxyProcessParameters.handoverShutdown } : undefined;\n this.processName = unsProxyProcessParameters.processName;\n this.processId = randomBytes(16).toString(\"hex\");\n this.handoverId = unsProxyProcessParameters.handoverId ?? process.env[\"UNS_HANDOVER_ID\"];\n const { name: packageName, version } = PACKAGE_INFO;\n\n // Instantiate the topic builder.\n const topicBuilder = new MqttTopicBuilder(\n `uns-infra/${MqttTopicBuilder.sanitizeTopicPart(packageName)}/${MqttTopicBuilder.sanitizeTopicPart(version)}/${MqttTopicBuilder.sanitizeTopicPart(this.processName)}/`,\n );\n\n // Generate topics.\n const processStatusTopic = topicBuilder.getProcessStatusTopic();\n const handoverTopic = topicBuilder.getHandoverTopic();\n const wildcardActiveTopic = topicBuilder.getWildcardActiveTopic();\n const serviceMetadataTopic = topicBuilder.getServiceMetadataTopic();\n\n this.processStatusTopic = processStatusTopic;\n this.serviceMetadataTopic = serviceMetadataTopic;\n\n // Configure MQTT topics for subscription.\n const mqttSubToTopics = unsProxyProcessParameters?.mqttSubToTopics ?? [wildcardActiveTopic, handoverTopic];\n const mqttParameters: IMqttParameters = {\n mqttSubToTopics,\n username: unsProxyProcessParameters?.username ?? \"\",\n password: unsProxyProcessParameters?.password ?? \"\",\n mqttSSL: unsProxyProcessParameters?.mqttSSL ?? false,\n statusTopic: this.processStatusTopic,\n clientId: unsProxyProcessParameters?.clientId ?? `${this.processName}-${this.processId}`,\n hosts: unsProxyProcessParameters?.hosts,\n servers: unsProxyProcessParameters?.servers,\n port: unsProxyProcessParameters?.port,\n protocol: unsProxyProcessParameters?.protocol,\n keepalive: unsProxyProcessParameters?.keepalive,\n clean: unsProxyProcessParameters?.clean,\n connectTimeout: unsProxyProcessParameters?.connectTimeout,\n reconnectPeriod: unsProxyProcessParameters?.reconnectPeriod,\n reconnectOnConnackError: unsProxyProcessParameters?.reconnectOnConnackError,\n resubscribe: unsProxyProcessParameters?.resubscribe,\n queueQoSZero: unsProxyProcessParameters?.queueQoSZero,\n rejectUnauthorized: unsProxyProcessParameters?.rejectUnauthorized ?? false,\n properties: unsProxyProcessParameters?.properties,\n ca: unsProxyProcessParameters?.ca,\n cert: unsProxyProcessParameters?.cert,\n key: unsProxyProcessParameters?.key,\n servername: unsProxyProcessParameters?.servername,\n };\n\n // Initialize MQTT proxy and start connection.\n this.processMqttProxy = new MqttProxy(mqttHost, this.processName, mqttParameters);\n this.processMqttProxy.start();\n\n // Instantiate and start the StatusMonitor for memory and status updates.\n this.statusMonitor = new StatusMonitor(\n this.processMqttProxy,\n this.processStatusTopic,\n () => this.active,\n MQTT_UPDATE_INTERVAL,\n MQTT_UPDATE_INTERVAL,\n { processName: this.processName, processId: this.processId },\n );\n this.statusMonitor.start();\n }\n\n /**\n * Initializes the HandoverManager instance and sets up event listeners for handover and MQTT input events.\n * Determines handover and force start modes based on process arguments.\n */\n private initHandoverManager(instanceMode: string, handover: boolean, handoverId?: string) {\n const handoverRequestEnabled = instanceMode == \"handover\" ? true : false;\n const forceStartEnabled = instanceMode == \"force\" ? true : false;\n\n this.handoverManager = new HandoverManager(\n this.processName,\n this.processId,\n this.processMqttProxy,\n this.unsMqttProxies,\n handoverRequestEnabled,\n handover ?? true,\n forceStartEnabled,\n handoverId,\n this.handoverShutdown,\n );\n\n // Listen for handover events.\n this.handoverManager.event.on(\"handoverManager\", (event) => {\n this.active = event.active;\n });\n\n // Delegate MQTT events to the HandoverManager.\n this.mqttInputHandler = async (event: UnsEvents[\"input\"]) => {\n await this.handoverManager.handleMqttMessage(event);\n };\n this.processMqttProxy.event.on(\"input\", this.mqttInputHandler);\n }\n\n /**\n * Creates a new UNS proxy instance and stores it for future management.\n */\n public async createUnsMqttProxy(\n mqttHost: string,\n instanceName: string,\n instanceMode: string,\n handover: boolean,\n unsParameters?: IUnsParameters,\n ): Promise<UnsMqttProxy> {\n if (unsParameters?.publishQueue && unsParameters.publishQueue.enabled !== false && handover) {\n throw new Error(\"Persistent MQTT output requires handover=false and one owner; legacy RAM handover does not transfer an outbox\");\n }\n // Wait until the MQTT connection is established before proceeding.\n await this.waitForProcessConnection();\n\n // Currently handover manager can handle only mqtt events\n if (!this.handoverManager) {\n this.initHandoverManager(\n instanceMode,\n handover,\n this.handoverId,\n );\n }\n\n const resolvedUnsParameters: IUnsParameters = {\n ...(unsParameters ?? {}),\n clientId: unsParameters?.clientId ?? `${this.processName}-${instanceName}-${this.processId}`,\n };\n const unsMqttProxy = new UnsMqttProxy(mqttHost, this.processName, instanceName, resolvedUnsParameters);\n\n // Listen for UNS proxy producing topics and publish them via MQTT.\n unsMqttProxy.event.on(\"unsProxyProducedTopics\", (event) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(event.producedTopics));\n });\n\n // Listen for UNS proxy status events and publish them via MQTT.\n unsMqttProxy.event.on(\"mqttProxyStatus\", (event) => {\n const time = UnsPacket.formatToISO8601(new Date());\n const unsMessage: IUnsMessage = { data: { time, value: event.value, uom: event.uom } };\n UnsPacket.unsPacketFromUnsMessage(unsMessage).then((packet) => {\n this.processMqttProxy.publish(event.statusTopic, JSON.stringify(packet));\n });\n });\n\n this.unsMqttProxies.push(unsMqttProxy);\n return unsMqttProxy;\n }\n\n public async waitForProcessConnection(): Promise<void> {\n while (!this.processMqttProxy?.isConnected) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n }\n\n /**\n * Publishes retained product/system service metadata for controller discovery.\n *\n * The payload is intentionally separate from the volatile active/alive status\n * topics. Controllers can combine this retained identity/capability metadata\n * with live process status to decide whether a service is currently healthy.\n */\n public async publishServiceMetadata(metadata: UnsServiceMetadataInput): Promise<UnsServiceMetadata> {\n await this.waitForProcessConnection();\n const resolved = buildUnsServiceMetadata({\n processName: this.processName,\n processId: this.processId,\n metadata,\n });\n await this.processMqttProxy.publish(this.serviceMetadataTopic, JSON.stringify(resolved), { retain: true });\n return resolved;\n }\n\n /** Call after application input handlers and shutdown hooks are prepared. */\n public enableMigrationDrain(): void {\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (this.migrationDrainHandler) return;\n if (registry[MQTT_DRAIN_HANDLER]) throw Error(\"One migration drain owner is allowed per process\");\n this.migrationDrainHandler = () => this.drainForMigration();\n registry[MQTT_DRAIN_HANDLER] = this.migrationDrainHandler;\n (process as unknown as { emit(event: string, value: unknown): boolean }).emit(MQTT_DRAIN_READY_EVENT, { protocol: 1 });\n }\n\n /** Works without a Controller too; success means confirmed empty output and closed owners. */\n public drainForMigration(timeoutMs = this.handoverShutdown?.timeoutMs ?? 30_000): Promise<MqttDrainReceipt> {\n if (this.migrationDrainPromise) return this.migrationDrainPromise;\n this.migrationDrainPromise = (async () => {\n const receipt = await drainMqttForMigration({\n quiesce: async () => {\n this.handoverShutdown?.onRelease?.();\n await Promise.all(this.unsMqttProxies.map(proxy => proxy.setSubscriberPassiveAndDrainQueue()));\n },\n finishAccepted: async () => { await this.handoverShutdown?.drain(); },\n outputs: this.unsMqttProxies,\n timeoutMs,\n });\n await this.shutdown({ drain: true, timeoutMs });\n return receipt;\n })().catch(error => { this.migrationDrainPromise = null; throw error; });\n return this.migrationDrainPromise;\n }\n\n /** Stop process timers, status publication and all owned MQTT proxies. */\n public shutdown(options: UnsMqttProxyStopOptions = {}): Promise<void> {\n if (this.shutdownPromise) {\n return this.shutdownPromise;\n }\n\n this.shutdownPromise = this.performShutdown(options);\n return this.shutdownPromise;\n }\n\n private async performShutdown(options: UnsMqttProxyStopOptions): Promise<void> {\n logger.info(`${this.processName} - Shutting down UnsProxyProcess...`);\n const shutdownErrors: Error[] = [];\n\n try {\n this.statusMonitor.stop();\n await this.statusMonitor.publishInactiveStatus();\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping StatusMonitor or publishing passive state: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (this.mqttInputHandler) {\n try {\n this.processMqttProxy.event.off(\"input\", this.mqttInputHandler);\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error removing MQTT input handler: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n const proxyStopResults = await Promise.allSettled(this.unsMqttProxies.map((proxy) => proxy.stop(options)));\n for (const result of proxyStopResults) {\n if (result.status === \"rejected\") {\n const reason = result.reason instanceof Error ? result.reason : new Error(String(result.reason));\n logger.error(`${this.processName} - Error stopping UNS MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n }\n\n try {\n if (typeof this.processMqttProxy.stop === \"function\") {\n await this.processMqttProxy.stop();\n }\n } catch (e: any) {\n const reason = e instanceof Error ? e : new Error(String(e));\n logger.error(`${this.processName} - Error stopping MQTT proxy: ${reason.message}`);\n shutdownErrors.push(reason);\n }\n\n if (shutdownErrors.length > 0) {\n throw new AggregateError(shutdownErrors, `${this.processName} - Shutdown completed with errors.`);\n }\n\n if (this.migrationDrainHandler) {\n const registry = globalThis as unknown as Record<symbol, unknown>;\n if (registry[MQTT_DRAIN_HANDLER] === this.migrationDrainHandler) delete registry[MQTT_DRAIN_HANDLER];\n process.channel?.unref();\n }\n logger.info(`${this.processName} - Shutdown complete.`);\n }\n}\n\ninterface UnsProxyProcess {}\n\nexport default UnsProxyProcess;\nexport type { UnsServiceMetadata, UnsServiceMetadataInput };\nexport { UnsProxyProcess };\n"]}
@@ -293,6 +293,7 @@ export declare const baseSchema: z.ZodObject<{
293
293
  key: z.ZodOptional<z.ZodString>;
294
294
  servername: z.ZodOptional<z.ZodString>;
295
295
  publishQueue: z.ZodOptional<z.ZodObject<{
296
+ enabled: z.ZodDefault<z.ZodBoolean>;
296
297
  mode: z.ZodEnum<{
297
298
  buffered: "buffered";
298
299
  durable: "durable";
@@ -1 +1 @@
1
- {"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/uns-config/config-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAAmE,CAAC;AAG3F,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/uns-config/config-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CAAmE,CAAC;AAG3F,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC"}