@uns-kit/core 3.0.33 → 3.0.35

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 (62) hide show
  1. package/MIGRATIONS.md +50 -0
  2. package/dist/config/app-config.d.ts +1 -1
  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-handover-state.d.ts +48 -0
  6. package/dist/runtime/mqtt-handover-state.d.ts.map +1 -0
  7. package/dist/runtime/mqtt-handover-state.js +61 -0
  8. package/dist/runtime/mqtt-handover-state.js.map +1 -0
  9. package/dist/runtime/process-group-authorization.d.ts +72 -0
  10. package/dist/runtime/process-group-authorization.d.ts.map +1 -1
  11. package/dist/runtime/process-group-authorization.js +31 -0
  12. package/dist/runtime/process-group-authorization.js.map +1 -1
  13. package/dist/runtime/process-group-contract.d.ts +1 -0
  14. package/dist/runtime/process-group-contract.d.ts.map +1 -1
  15. package/dist/runtime/process-group-contract.js +2 -1
  16. package/dist/runtime/process-group-contract.js.map +1 -1
  17. package/dist/runtime/process-group-direct-contract.d.ts +181 -0
  18. package/dist/runtime/process-group-direct-contract.d.ts.map +1 -0
  19. package/dist/runtime/process-group-direct-contract.js +151 -0
  20. package/dist/runtime/process-group-direct-contract.js.map +1 -0
  21. package/dist/runtime/process-group-direct-review.d.ts +203 -0
  22. package/dist/runtime/process-group-direct-review.d.ts.map +1 -0
  23. package/dist/runtime/process-group-direct-review.js +263 -0
  24. package/dist/runtime/process-group-direct-review.js.map +1 -0
  25. package/dist/runtime/process-group-direct-runtime.d.ts +18 -0
  26. package/dist/runtime/process-group-direct-runtime.d.ts.map +1 -0
  27. package/dist/runtime/process-group-direct-runtime.js +154 -0
  28. package/dist/runtime/process-group-direct-runtime.js.map +1 -0
  29. package/dist/runtime/process-group-snapshot.mjs +44 -0
  30. package/dist/uns/handover-manager.d.ts +10 -1
  31. package/dist/uns/handover-manager.d.ts.map +1 -1
  32. package/dist/uns/handover-manager.js +113 -5
  33. package/dist/uns/handover-manager.js.map +1 -1
  34. package/dist/uns/uns-interfaces.d.ts +4 -0
  35. package/dist/uns/uns-interfaces.d.ts.map +1 -1
  36. package/dist/uns/uns-interfaces.js.map +1 -1
  37. package/dist/uns/uns-proxy-process.d.ts +1 -0
  38. package/dist/uns/uns-proxy-process.d.ts.map +1 -1
  39. package/dist/uns/uns-proxy-process.js +6 -2
  40. package/dist/uns/uns-proxy-process.js.map +1 -1
  41. package/dist/uns-config/config-schema.d.ts +4 -1
  42. package/dist/uns-config/config-schema.d.ts.map +1 -1
  43. package/dist/uns-config/uns-core-schema.d.ts +4 -1
  44. package/dist/uns-config/uns-core-schema.d.ts.map +1 -1
  45. package/dist/uns-config/uns-core-schema.js +1 -1
  46. package/dist/uns-config/uns-core-schema.js.map +1 -1
  47. package/dist/uns-mqtt/mqtt-proxy.d.ts +1 -0
  48. package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
  49. package/dist/uns-mqtt/mqtt-proxy.js +5 -0
  50. package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
  51. package/dist/uns-mqtt/mqtt-worker.d.ts.map +1 -1
  52. package/dist/uns-mqtt/mqtt-worker.js +13 -1
  53. package/dist/uns-mqtt/mqtt-worker.js.map +1 -1
  54. package/dist/uns-mqtt/throttled-queue.d.ts +8 -1
  55. package/dist/uns-mqtt/throttled-queue.d.ts.map +1 -1
  56. package/dist/uns-mqtt/throttled-queue.js +32 -4
  57. package/dist/uns-mqtt/throttled-queue.js.map +1 -1
  58. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +26 -2
  59. package/dist/uns-mqtt/uns-mqtt-proxy.d.ts.map +1 -1
  60. package/dist/uns-mqtt/uns-mqtt-proxy.js +82 -6
  61. package/dist/uns-mqtt/uns-mqtt-proxy.js.map +1 -1
  62. package/package.json +1 -1
@@ -0,0 +1,151 @@
1
+ import path from "node:path";
2
+ import { z } from "zod";
3
+ import { processGroupConfigurationSelectorSchema as selector } from "./process-group-contract.js";
4
+ import { groupPlacementSchema, placementKey } from "./process-group-control-contract.js";
5
+ const identity = z.string().regex(/^[a-z][a-z0-9-]{0,99}$/);
6
+ const digest = z.string().regex(/^[a-f0-9]{64}$/);
7
+ const absolute = z
8
+ .string()
9
+ .min(1)
10
+ .max(512)
11
+ .refine((v) => path.isAbsolute(v) && path.resolve(v) === v);
12
+ const relative = z
13
+ .string()
14
+ .min(1)
15
+ .max(512)
16
+ .refine((v) => !path.isAbsolute(v) && path.normalize(v) === v && !v.split(/[\\/]/).some((p) => p === ".." || p === ".") && !v.includes("\0"));
17
+ /** Package data, never launch authority. Selectors are reusable across applications. */
18
+ const resource = z.discriminatedUnion("kind", [
19
+ z.strictObject({
20
+ kind: z.literal("file"),
21
+ manifestPath: selector,
22
+ manifests: z
23
+ .array(z.strictObject({ id: identity, file: relative }))
24
+ .min(1)
25
+ .max(64),
26
+ }),
27
+ z.strictObject({ kind: z.literal("configuration"), groupPath: selector }),
28
+ ]);
29
+ export const processGroupDirectDescriptorSchema = z
30
+ .strictObject({
31
+ protocolVersion: z.literal(1),
32
+ namespace: identity,
33
+ publisherPath: selector,
34
+ journalPath: selector,
35
+ runtimeRolePath: selector,
36
+ directRole: identity,
37
+ resources: z.array(resource).min(1).max(2),
38
+ match: z.strictObject({ path: selector, value: z.string().min(1).max(100) }).optional(),
39
+ })
40
+ .superRefine((v, c) => {
41
+ if (new Set(v.resources.map((r) => r.kind)).size !== v.resources.length)
42
+ c.addIssue({ code: "custom", message: "Distinct direct resource kinds required" });
43
+ for (const r of v.resources) {
44
+ const resourcePath = r.kind === "file" ? r.manifestPath : r.groupPath;
45
+ if (resourcePath.length <= v.publisherPath.length || !v.publisherPath.every((key, i) => resourcePath[i] === key))
46
+ c.addIssue({ code: "custom", message: "Direct resource selector must be a publisher leaf" });
47
+ if (r.kind === "file" &&
48
+ (new Set(r.manifests.map((m) => m.id)).size !== r.manifests.length || new Set(r.manifests.map((m) => m.file)).size !== r.manifests.length))
49
+ c.addIssue({ code: "custom", message: "Distinct direct manifest resources required" });
50
+ }
51
+ const paths = [v.publisherPath, v.journalPath, v.runtimeRolePath].map((p) => p.join("."));
52
+ if (new Set(paths).size !== paths.length || paths.some((p, i) => paths.some((q, j) => i !== j && q.startsWith(p + "."))))
53
+ c.addIssue({ code: "custom", message: "Distinct lifecycle selectors required" });
54
+ });
55
+ export const processGroupDirectInputSchema = z
56
+ .strictObject({
57
+ protocolVersion: z.literal(1),
58
+ source: z.strictObject({ publisher: groupPlacementSchema, receiver: groupPlacementSchema }),
59
+ target: groupPlacementSchema,
60
+ })
61
+ .superRefine((v, c) => {
62
+ const all = [v.source.publisher, v.source.receiver, v.target];
63
+ if (new Set(all.map(placementKey)).size !== 3 ||
64
+ all.some((p) => p.controller !== all[0].controller || p.rttNode !== all[0].rttNode) ||
65
+ v.source.publisher.version !== v.source.receiver.version)
66
+ c.addIssue({ code: "custom", message: "Three distinct placements with one owning controller/package and one source-pair version required" });
67
+ });
68
+ export const processGroupDirectRequestSchema = z
69
+ .strictObject({
70
+ protocolVersion: z.literal(1),
71
+ controllerName: groupPlacementSchema.shape.controller,
72
+ id: z.string().uuid(),
73
+ action: z.enum(["preview", "prepare", "get", "execute", "rollback", "close-recovery"]),
74
+ input: processGroupDirectInputSchema.optional(),
75
+ expectedFingerprint: digest.optional(),
76
+ expectedRevision: z.number().int().positive().optional(),
77
+ })
78
+ .superRefine((v, c) => {
79
+ if ((["preview", "prepare"].includes(v.action) && !v.input) ||
80
+ (["prepare", "execute", "rollback", "close-recovery"].includes(v.action) && !v.expectedFingerprint) ||
81
+ (["execute", "rollback", "close-recovery"].includes(v.action) && !v.expectedRevision) ||
82
+ (v.input && v.input.target.controller !== v.controllerName))
83
+ c.addIssue({ code: "custom", message: "Exact transition identity, owning member and reviewed revision required" });
84
+ });
85
+ export const retiredJournalReferenceSchema = z
86
+ .strictObject({
87
+ directory: absolute,
88
+ journalId: z.string().uuid(),
89
+ journalContractSha256: digest,
90
+ generationId: identity,
91
+ groupSha256: digest.optional(),
92
+ contractVersion: z.union([z.literal(1), z.literal(2)]),
93
+ maxRecords: z.number().int().min(1).max(100000),
94
+ maxBytes: z
95
+ .number()
96
+ .int()
97
+ .min(1024)
98
+ .max(256 * 1024 * 1024),
99
+ minFreeBytes: z
100
+ .number()
101
+ .int()
102
+ .min(0)
103
+ .max(1024 * 1024 * 1024),
104
+ profiles: z
105
+ .array(z.strictObject({ processName: identity, mappingSha256: digest, dataGroup: identity }))
106
+ .min(2)
107
+ .max(16),
108
+ })
109
+ .superRefine((v, c) => {
110
+ if (v.contractVersion === 2 && !v.groupSha256)
111
+ c.addIssue({ code: "custom", message: "Configuration generation identity required" });
112
+ if (new Set(v.profiles.map((p) => p.processName)).size !== v.profiles.length)
113
+ c.addIssue({ code: "custom", message: "Distinct retained profiles required" });
114
+ });
115
+ const member = z.strictObject({
116
+ placement: groupPlacementSchema,
117
+ processName: identity,
118
+ configurationSha256: digest,
119
+ artifactSha256: digest,
120
+ });
121
+ export const processGroupRetirementPolicySchema = z
122
+ .strictObject({
123
+ schemaVersion: z.literal(5),
124
+ kind: z.literal("uns-process-group-direct-retirement"),
125
+ protocolVersion: z.literal(1),
126
+ operationId: z.string().uuid(),
127
+ packageName: z.string().min(1).max(214),
128
+ namespace: identity,
129
+ groupId: identity,
130
+ controllerName: groupPlacementSchema.shape.controller,
131
+ stateRoot: absolute,
132
+ recovery: z.enum(["open", "closed"]),
133
+ journal: retiredJournalReferenceSchema,
134
+ sourcePolicyJson: z.string().min(1).max(32768),
135
+ sourcePolicySha256: digest,
136
+ source: z.strictObject({
137
+ publisher: member.extend({ policyConfigurationSha256: digest }),
138
+ receiver: member.extend({ policyConfigurationSha256: digest }),
139
+ }),
140
+ target: member.extend({ packageRoot: absolute, descriptorSha256: digest, resourceSha256: digest, channelsSha256: digest }),
141
+ })
142
+ .superRefine((v, c) => {
143
+ if (v.target.processName !== v.source.publisher.processName ||
144
+ v.source.receiver.processName === v.target.processName ||
145
+ v.source.publisher.placement.controller !== v.controllerName ||
146
+ v.source.receiver.placement.controller !== v.controllerName ||
147
+ v.target.placement.controller !== v.controllerName ||
148
+ v.journal.profiles.some((p) => [v.target.processName, v.source.receiver.processName].includes(p.processName)))
149
+ c.addIssue({ code: "custom", message: "Exact paired and direct ownership identities required" });
150
+ });
151
+ //# sourceMappingURL=process-group-direct-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-direct-contract.js","sourceRoot":"","sources":["../../src/runtime/process-group-direct-contract.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { z } from \"zod\";\n\nimport { processGroupConfigurationSelectorSchema as selector } from \"./process-group-contract.js\";\nimport { groupPlacementSchema, placementKey } from \"./process-group-control-contract.js\";\n\nconst identity = z.string().regex(/^[a-z][a-z0-9-]{0,99}$/);\nconst digest = z.string().regex(/^[a-f0-9]{64}$/);\nconst absolute = z\n .string()\n .min(1)\n .max(512)\n .refine((v) => path.isAbsolute(v) && path.resolve(v) === v);\nconst relative = z\n .string()\n .min(1)\n .max(512)\n .refine((v) => !path.isAbsolute(v) && path.normalize(v) === v && !v.split(/[\\\\/]/).some((p) => p === \"..\" || p === \".\") && !v.includes(\"\\0\"));\n\n/** Package data, never launch authority. Selectors are reusable across applications. */\nconst resource = z.discriminatedUnion(\"kind\", [\n z.strictObject({\n kind: z.literal(\"file\"),\n manifestPath: selector,\n manifests: z\n .array(z.strictObject({ id: identity, file: relative }))\n .min(1)\n .max(64),\n }),\n z.strictObject({ kind: z.literal(\"configuration\"), groupPath: selector }),\n]);\nexport const processGroupDirectDescriptorSchema = z\n .strictObject({\n protocolVersion: z.literal(1),\n namespace: identity,\n publisherPath: selector,\n journalPath: selector,\n runtimeRolePath: selector,\n directRole: identity,\n resources: z.array(resource).min(1).max(2),\n match: z.strictObject({ path: selector, value: z.string().min(1).max(100) }).optional(),\n })\n .superRefine((v, c) => {\n if (new Set(v.resources.map((r) => r.kind)).size !== v.resources.length)\n c.addIssue({ code: \"custom\", message: \"Distinct direct resource kinds required\" });\n for (const r of v.resources) {\n const resourcePath = r.kind === \"file\" ? r.manifestPath : r.groupPath;\n if (resourcePath.length <= v.publisherPath.length || !v.publisherPath.every((key, i) => resourcePath[i] === key))\n c.addIssue({ code: \"custom\", message: \"Direct resource selector must be a publisher leaf\" });\n if (\n r.kind === \"file\" &&\n (new Set(r.manifests.map((m) => m.id)).size !== r.manifests.length || new Set(r.manifests.map((m) => m.file)).size !== r.manifests.length)\n )\n c.addIssue({ code: \"custom\", message: \"Distinct direct manifest resources required\" });\n }\n const paths = [v.publisherPath, v.journalPath, v.runtimeRolePath].map((p) => p.join(\".\"));\n if (new Set(paths).size !== paths.length || paths.some((p, i) => paths.some((q, j) => i !== j && q.startsWith(p + \".\"))))\n c.addIssue({ code: \"custom\", message: \"Distinct lifecycle selectors required\" });\n });\nexport type ProcessGroupDirectDescriptor = z.infer<typeof processGroupDirectDescriptorSchema>;\nexport const processGroupDirectInputSchema = z\n .strictObject({\n protocolVersion: z.literal(1),\n source: z.strictObject({ publisher: groupPlacementSchema, receiver: groupPlacementSchema }),\n target: groupPlacementSchema,\n })\n .superRefine((v, c) => {\n const all = [v.source.publisher, v.source.receiver, v.target];\n if (\n new Set(all.map(placementKey)).size !== 3 ||\n all.some((p) => p.controller !== all[0]!.controller || p.rttNode !== all[0]!.rttNode) ||\n v.source.publisher.version !== v.source.receiver.version\n )\n c.addIssue({ code: \"custom\", message: \"Three distinct placements with one owning controller/package and one source-pair version required\" });\n });\nexport type ProcessGroupDirectInput = z.infer<typeof processGroupDirectInputSchema>;\nexport const processGroupDirectRequestSchema = z\n .strictObject({\n protocolVersion: z.literal(1),\n controllerName: groupPlacementSchema.shape.controller,\n id: z.string().uuid(),\n action: z.enum([\"preview\", \"prepare\", \"get\", \"execute\", \"rollback\", \"close-recovery\"]),\n input: processGroupDirectInputSchema.optional(),\n expectedFingerprint: digest.optional(),\n expectedRevision: z.number().int().positive().optional(),\n })\n .superRefine((v, c) => {\n if (\n ([\"preview\", \"prepare\"].includes(v.action) && !v.input) ||\n ([\"prepare\", \"execute\", \"rollback\", \"close-recovery\"].includes(v.action) && !v.expectedFingerprint) ||\n ([\"execute\", \"rollback\", \"close-recovery\"].includes(v.action) && !v.expectedRevision) ||\n (v.input && v.input.target.controller !== v.controllerName)\n )\n c.addIssue({ code: \"custom\", message: \"Exact transition identity, owning member and reviewed revision required\" });\n });\nexport type ProcessGroupDirectRequest = z.infer<typeof processGroupDirectRequestSchema>;\nexport const retiredJournalReferenceSchema = z\n .strictObject({\n directory: absolute,\n journalId: z.string().uuid(),\n journalContractSha256: digest,\n generationId: identity,\n groupSha256: digest.optional(),\n contractVersion: z.union([z.literal(1), z.literal(2)]),\n maxRecords: z.number().int().min(1).max(100000),\n maxBytes: z\n .number()\n .int()\n .min(1024)\n .max(256 * 1024 * 1024),\n minFreeBytes: z\n .number()\n .int()\n .min(0)\n .max(1024 * 1024 * 1024),\n profiles: z\n .array(z.strictObject({ processName: identity, mappingSha256: digest, dataGroup: identity }))\n .min(2)\n .max(16),\n })\n .superRefine((v, c) => {\n if (v.contractVersion === 2 && !v.groupSha256) c.addIssue({ code: \"custom\", message: \"Configuration generation identity required\" });\n if (new Set(v.profiles.map((p) => p.processName)).size !== v.profiles.length)\n c.addIssue({ code: \"custom\", message: \"Distinct retained profiles required\" });\n });\nexport type RetiredJournalReference = z.infer<typeof retiredJournalReferenceSchema>;\nconst member = z.strictObject({\n placement: groupPlacementSchema,\n processName: identity,\n configurationSha256: digest,\n artifactSha256: digest,\n});\nexport const processGroupRetirementPolicySchema = z\n .strictObject({\n schemaVersion: z.literal(5),\n kind: z.literal(\"uns-process-group-direct-retirement\"),\n protocolVersion: z.literal(1),\n operationId: z.string().uuid(),\n packageName: z.string().min(1).max(214),\n namespace: identity,\n groupId: identity,\n controllerName: groupPlacementSchema.shape.controller,\n stateRoot: absolute,\n recovery: z.enum([\"open\", \"closed\"]),\n journal: retiredJournalReferenceSchema,\n sourcePolicyJson: z.string().min(1).max(32768),\n sourcePolicySha256: digest,\n source: z.strictObject({\n publisher: member.extend({ policyConfigurationSha256: digest }),\n receiver: member.extend({ policyConfigurationSha256: digest }),\n }),\n target: member.extend({ packageRoot: absolute, descriptorSha256: digest, resourceSha256: digest, channelsSha256: digest }),\n })\n .superRefine((v, c) => {\n if (\n v.target.processName !== v.source.publisher.processName ||\n v.source.receiver.processName === v.target.processName ||\n v.source.publisher.placement.controller !== v.controllerName ||\n v.source.receiver.placement.controller !== v.controllerName ||\n v.target.placement.controller !== v.controllerName ||\n v.journal.profiles.some((p) => [v.target.processName, v.source.receiver.processName].includes(p.processName))\n )\n c.addIssue({ code: \"custom\", message: \"Exact paired and direct ownership identities required\" });\n });\nexport type ProcessGroupRetirementPolicy = z.infer<typeof processGroupRetirementPolicySchema>;\n"]}
@@ -0,0 +1,203 @@
1
+ import { type ProcessGroupDirectDescriptor } from "./process-group-direct-contract.js";
2
+ import type { GenerationJournalReference } from "./process-group-generation.js";
3
+ import type { UpgradeConfiguration } from "./process-group-upgrade.js";
4
+ type Config = UpgradeConfiguration;
5
+ export type DirectTransitionConfigurations = {
6
+ source: {
7
+ publisher: Config;
8
+ receiver: Config;
9
+ };
10
+ target: Config;
11
+ };
12
+ export declare function processGroupDirectDescriptor(packageRoot: string): ProcessGroupDirectDescriptor | undefined;
13
+ export declare function describeDirectProcessGroup(c: Config): {
14
+ descriptor: {
15
+ protocolVersion: 1;
16
+ namespace: string;
17
+ publisherPath: string[];
18
+ journalPath: string[];
19
+ runtimeRolePath: string[];
20
+ directRole: string;
21
+ resources: ({
22
+ kind: "file";
23
+ manifestPath: string[];
24
+ manifests: {
25
+ id: string;
26
+ file: string;
27
+ }[];
28
+ } | {
29
+ kind: "configuration";
30
+ groupPath: string[];
31
+ })[];
32
+ match?: {
33
+ path: string[];
34
+ value: string;
35
+ };
36
+ };
37
+ resource: {
38
+ kind: "configuration";
39
+ groupPath: string[];
40
+ };
41
+ groupId: string;
42
+ processName: string;
43
+ resourceSha256: string;
44
+ profiles: {
45
+ processName: string;
46
+ mappingSha256: string;
47
+ dataGroup: string;
48
+ }[];
49
+ snapshot: import("./configuration-group-contract.js").ConfigurationGroupSnapshot;
50
+ manifest?: undefined;
51
+ manifestPath?: undefined;
52
+ manifestFile?: undefined;
53
+ } | {
54
+ descriptor: {
55
+ protocolVersion: 1;
56
+ namespace: string;
57
+ publisherPath: string[];
58
+ journalPath: string[];
59
+ runtimeRolePath: string[];
60
+ directRole: string;
61
+ resources: ({
62
+ kind: "file";
63
+ manifestPath: string[];
64
+ manifests: {
65
+ id: string;
66
+ file: string;
67
+ }[];
68
+ } | {
69
+ kind: "configuration";
70
+ groupPath: string[];
71
+ })[];
72
+ match?: {
73
+ path: string[];
74
+ value: string;
75
+ };
76
+ };
77
+ resource: {
78
+ kind: "file";
79
+ manifestPath: string[];
80
+ manifests: {
81
+ id: string;
82
+ file: string;
83
+ }[];
84
+ };
85
+ groupId: string;
86
+ processName: string;
87
+ resourceSha256: string;
88
+ profiles: {
89
+ processName: string;
90
+ mappingSha256: string;
91
+ dataGroup: string;
92
+ }[];
93
+ manifest: {
94
+ schemaVersion: 1;
95
+ id: string;
96
+ inputTopic: string;
97
+ processName: string;
98
+ profiles: {
99
+ id: string;
100
+ processName: string;
101
+ mappingFile: string;
102
+ mappingSha256: string;
103
+ dataGroup: string;
104
+ }[];
105
+ };
106
+ manifestPath: string;
107
+ manifestFile: string;
108
+ snapshot?: undefined;
109
+ };
110
+ /** Data-only installed-resource review. Does not stop, initialize, rewrite or grant launch authority. */
111
+ export declare function reviewInstalledProcessGroupDirectTransition(operationId: string, rawInput: unknown, configs: DirectTransitionConfigurations, stateRoot: string, excludedUnsFields?: readonly string[]): {
112
+ review: {
113
+ protocolVersion: 1;
114
+ kind: "paired-to-direct";
115
+ input: {
116
+ protocolVersion: 1;
117
+ source: {
118
+ publisher: {
119
+ controller: string;
120
+ rttNode: string;
121
+ version: string;
122
+ instanceId: string;
123
+ };
124
+ receiver: {
125
+ controller: string;
126
+ rttNode: string;
127
+ version: string;
128
+ instanceId: string;
129
+ };
130
+ };
131
+ target: {
132
+ controller: string;
133
+ rttNode: string;
134
+ version: string;
135
+ instanceId: string;
136
+ };
137
+ };
138
+ operationId: string;
139
+ policyFile: string;
140
+ sourcePolicySha256: string;
141
+ targetPolicySha256: string;
142
+ journal: GenerationJournalReference;
143
+ source: {
144
+ publisher: {
145
+ placement: {
146
+ controller: string;
147
+ rttNode: string;
148
+ version: string;
149
+ instanceId: string;
150
+ };
151
+ processName: string;
152
+ configurationSha256: string;
153
+ artifactSha256: string;
154
+ policyConfigurationSha256: string;
155
+ };
156
+ receiver: {
157
+ placement: {
158
+ controller: string;
159
+ rttNode: string;
160
+ version: string;
161
+ instanceId: string;
162
+ };
163
+ processName: string;
164
+ configurationSha256: string;
165
+ artifactSha256: string;
166
+ policyConfigurationSha256: string;
167
+ };
168
+ };
169
+ target: {
170
+ placement: {
171
+ controller: string;
172
+ rttNode: string;
173
+ version: string;
174
+ instanceId: string;
175
+ };
176
+ processName: string;
177
+ configurationSha256: string;
178
+ artifactSha256: string;
179
+ packageRoot: string;
180
+ descriptorSha256: string;
181
+ resourceSha256: string;
182
+ channelsSha256: string;
183
+ };
184
+ namespace: string;
185
+ groupId: string;
186
+ delivery: {
187
+ inputPausePossible: boolean;
188
+ exactlyOnceOutput: boolean;
189
+ brokerReplayNotTransferred: boolean;
190
+ };
191
+ usage: {
192
+ records: number;
193
+ bytes: number;
194
+ admitted: number;
195
+ completed: number;
196
+ lastSequence: number;
197
+ };
198
+ };
199
+ sourcePolicy: Buffer<ArrayBufferLike>;
200
+ targetPolicy: Buffer<ArrayBuffer>;
201
+ };
202
+ export {};
203
+ //# sourceMappingURL=process-group-direct-review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-group-direct-review.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-direct-review.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,4BAA4B,EAMlC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAShF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,KAAK,MAAM,GAAG,oBAAoB,CAAC;AACnC,MAAM,MAAM,8BAA8B,GAAG;IAAE,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAMjH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,4BAA4B,GAAG,SAAS,CAK1G;AACD,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsDnD;AA6BD,yGAAyG;AACzG,wBAAgB,2CAA2C,CACzD,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,8BAA8B,EACvC,SAAS,EAAE,MAAM,EACjB,iBAAiB,GAAE,SAAS,MAAM,EAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8J1C"}
@@ -0,0 +1,263 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { configurationGroupSnapshot, configurationResourceHash } from "./configuration-group-contract.js";
4
+ import { authorizeProcessGroupRuntime, processGroupManifestSchema } from "./process-group-authorization.js";
5
+ import { processGroupJournalContract, processGroupJournalSchema, processGroupSourceIdentity, readConfigurationSelector, resolvedProcessGroupChannels, } from "./process-group-contract.js";
6
+ import { processGroupDirectDescriptorSchema, processGroupDirectInputSchema, processGroupRetirementPolicySchema, retiredJournalReferenceSchema, } from "./process-group-direct-contract.js";
7
+ import { describeInstalledProcessGroupGeneration, inspectGenerationJournal } from "./process-group-generation.js";
8
+ import { groupArtifactHash, groupChannelsHash, configurationAuthorizationHash as hash, readProcessGroupResource as read, sha256, } from "./process-group-resources.js";
9
+ import { normalizeRuntimeProcessGroup, selectedProcessGroupDescriptor } from "./process-group-runtime-selection.js";
10
+ const inside = (root, file) => {
11
+ const resolved = path.resolve(root, file);
12
+ if (!resolved.startsWith(path.resolve(root) + path.sep))
13
+ throw Error("Direct resource escapes installed package");
14
+ return read(resolved);
15
+ };
16
+ export function processGroupDirectDescriptor(packageRoot) {
17
+ const pkg = JSON.parse(read(path.join(packageRoot, "package.json")).toString());
18
+ return pkg.unsDatahub?.processGroupDirectRuntime === undefined
19
+ ? undefined
20
+ : processGroupDirectDescriptorSchema.parse(pkg.unsDatahub.processGroupDirectRuntime);
21
+ }
22
+ export function describeDirectProcessGroup(c) {
23
+ const descriptor = processGroupDirectDescriptor(c.packageRoot);
24
+ if (!descriptor ||
25
+ (descriptor.match && readConfigurationSelector(c.raw, descriptor.match.path) !== descriptor.match.value) ||
26
+ readConfigurationSelector(c.raw, descriptor.runtimeRolePath) !== descriptor.directRole ||
27
+ readConfigurationSelector(c.raw, descriptor.journalPath) !== undefined)
28
+ throw Error("Exact declared direct mode without an input journal required");
29
+ const publisher = readConfigurationSelector(c.raw, descriptor.publisherPath);
30
+ if (!publisher || typeof publisher !== "object" || Array.isArray(publisher))
31
+ throw Error("Explicit direct publisher required");
32
+ const selectedResources = descriptor.resources.filter((r) => readConfigurationSelector(c.raw, r.kind === "file" ? r.manifestPath : r.groupPath) !== undefined);
33
+ if (selectedResources.length !== 1)
34
+ throw Error("Select exactly one declared direct resource");
35
+ const resource = selectedResources[0];
36
+ if (resource.kind === "configuration") {
37
+ const snapshot = configurationGroupSnapshot(readConfigurationSelector(c.raw, resource.groupPath));
38
+ if (configurationResourceHash(readConfigurationSelector(c.resolved, resource.groupPath)) !==
39
+ configurationResourceHash(readConfigurationSelector(c.raw, resource.groupPath)))
40
+ throw Error("Resolved direct business resource differs from its reviewed configuration");
41
+ return {
42
+ descriptor,
43
+ resource,
44
+ groupId: snapshot.group.id,
45
+ processName: snapshot.group.processName,
46
+ resourceSha256: snapshot.sha256,
47
+ profiles: snapshot.profiles.map((p) => ({ processName: p.processName, mappingSha256: p.resourceSha256, dataGroup: p.dataGroup })),
48
+ snapshot,
49
+ };
50
+ }
51
+ const manifestPath = readConfigurationSelector(c.raw, resource.manifestPath);
52
+ const selected = resource.manifests.find((m) => m.file === manifestPath);
53
+ if (!selected)
54
+ throw Error("Unregistered direct manifest");
55
+ if (readConfigurationSelector(c.resolved, resource.manifestPath) !== selected.file)
56
+ throw Error("Resolved direct manifest selection changed");
57
+ const bytes = inside(c.packageRoot, selected.file), manifest = processGroupManifestSchema.parse(JSON.parse(bytes.toString()));
58
+ if (manifest.id !== selected.id)
59
+ throw Error("Direct manifest identity differs");
60
+ for (const p of manifest.profiles)
61
+ if (sha256(inside(c.packageRoot, path.join(path.dirname(selected.file), p.mappingFile))) !== p.mappingSha256)
62
+ throw Error("Direct profile resource changed");
63
+ return {
64
+ descriptor,
65
+ resource,
66
+ groupId: manifest.id,
67
+ processName: manifest.processName,
68
+ resourceSha256: sha256(bytes),
69
+ profiles: manifest.profiles.map(({ processName, mappingSha256, dataGroup }) => ({ processName, mappingSha256, dataGroup })),
70
+ manifest,
71
+ manifestPath: selected.file,
72
+ manifestFile: path.resolve(c.packageRoot, selected.file),
73
+ };
74
+ }
75
+ function remove(raw, keys) {
76
+ let current = raw;
77
+ const parents = [];
78
+ for (const key of keys.slice(0, -1)) {
79
+ const next = current[key];
80
+ if (!next || typeof next !== "object" || Array.isArray(next))
81
+ return;
82
+ parents.push([current, key]);
83
+ current = next;
84
+ }
85
+ delete current[keys.at(-1)];
86
+ for (const [parent, key] of parents.reverse()) {
87
+ const value = parent[key];
88
+ if (value && typeof value === "object" && !Object.keys(value).length)
89
+ delete parent[key];
90
+ else
91
+ break;
92
+ }
93
+ }
94
+ function projection(raw, d, excluded) {
95
+ const copy = structuredClone(raw);
96
+ remove(copy, d.journalPath);
97
+ remove(copy, d.runtimeRolePath);
98
+ for (const r of d.resources)
99
+ if (r.kind === "file")
100
+ remove(copy, r.manifestPath);
101
+ const uns = copy["uns"];
102
+ if (uns && typeof uns === "object" && !Array.isArray(uns))
103
+ for (const key of excluded)
104
+ delete uns[key];
105
+ // Removing a lifecycle leaf must not turn an otherwise empty publisher into a difference.
106
+ const publisher = readConfigurationSelector(copy, d.publisherPath);
107
+ if (publisher && typeof publisher === "object" && !Object.keys(publisher).length)
108
+ remove(copy, d.publisherPath);
109
+ return hash(copy);
110
+ }
111
+ /** Data-only installed-resource review. Does not stop, initialize, rewrite or grant launch authority. */
112
+ export function reviewInstalledProcessGroupDirectTransition(operationId, rawInput, configs, stateRoot, excludedUnsFields = []) {
113
+ const input = processGroupDirectInputSchema.parse(rawInput), owner = input.target.controller, first = configs.source.publisher, target = configs.target;
114
+ const pkg = (c) => JSON.parse(read(path.join(c.packageRoot, "package.json")).toString());
115
+ for (const [p, c] of [
116
+ [input.source.publisher, first],
117
+ [input.source.receiver, configs.source.receiver],
118
+ [input.target, target],
119
+ ]) {
120
+ if (path.resolve(c.packageRoot, "instances", p.instanceId) !== c.instanceDirectory ||
121
+ fs.realpathSync(c.instanceDirectory) !== c.instanceDirectory ||
122
+ pkg(c).name !== p.rttNode ||
123
+ pkg(c).version !== p.version)
124
+ throw Error("Exact installed package and instance placement required");
125
+ }
126
+ const context = (c) => ({
127
+ packageRoot: c.packageRoot,
128
+ instanceDirectory: c.instanceDirectory,
129
+ rawConfiguration: c.raw,
130
+ channels: resolvedProcessGroupChannels(c.resolved),
131
+ controllerName: owner,
132
+ stateRoot,
133
+ });
134
+ const old = authorizeProcessGroupRuntime(context(first)), receiver = authorizeProcessGroupRuntime(context(configs.source.receiver));
135
+ if (old.role !== "target" ||
136
+ receiver.role !== "receiver" ||
137
+ old.file !== receiver.file ||
138
+ old.sha256 !== receiver.sha256 ||
139
+ old.directory !== receiver.directory ||
140
+ !old.journalId ||
141
+ old.journalId !== receiver.journalId)
142
+ throw Error("Exact authorized publisher/receiver owners required");
143
+ const sourcePolicy = read(old.file, true), sourceDescriptor = selectedProcessGroupDescriptor(first.packageRoot, first.raw);
144
+ if (!sourceDescriptor)
145
+ throw Error("Missing source shared contract");
146
+ const normalized = normalizeRuntimeProcessGroup(first.raw, sourceDescriptor), direct = describeDirectProcessGroup(target), d = direct.descriptor;
147
+ const namespace = sourceDescriptor.namespace;
148
+ if (d.namespace !== namespace ||
149
+ hash(d.publisherPath) !== hash(sourceDescriptor.publisherPath) ||
150
+ hash(d.journalPath) !== hash(sourceDescriptor.journalPath) ||
151
+ hash(d.runtimeRolePath) !== hash(sourceDescriptor.runtimeRolePath) ||
152
+ direct.groupId !== old.groupId ||
153
+ direct.processName !== old.groupProcessName ||
154
+ target.raw["uns"]?.["processName"] !== old.groupProcessName ||
155
+ projection(first.raw, d, excludedUnsFields) !== projection(target.raw, d, excludedUnsFields))
156
+ throw Error("Direct business configuration, selector or group identity changed");
157
+ const channels = groupChannelsHash(context(first).channels);
158
+ if (channels !== groupChannelsHash(context(configs.source.receiver).channels) || channels !== groupChannelsHash(context(target).channels))
159
+ throw Error("Direct broker/channel identity changed");
160
+ for (const c of [first, configs.source.receiver, target])
161
+ if (resolvedProcessGroupChannels(c.resolved)[2].publishQueue?.enabled === true)
162
+ throw Error("Initial direct retirement requires disabled disk MQTT output");
163
+ let reference, sourceResourceSha256;
164
+ if (sourceDescriptor.protocolVersion === 2) {
165
+ if (direct.resource.kind !== "configuration" || !direct.snapshot)
166
+ throw Error("Resource kind must remain configuration based");
167
+ const generation = describeInstalledProcessGroupGeneration(first);
168
+ reference = generation.reference;
169
+ sourceResourceSha256 = configurationGroupSnapshot(readConfigurationSelector(first.raw, sourceDescriptor.groupPath)).sha256;
170
+ }
171
+ else {
172
+ if (direct.resource.kind !== "file" || !direct.manifest)
173
+ throw Error("Resource kind must remain file based");
174
+ const journal = processGroupJournalSchema.parse(normalized.journal);
175
+ const declared = sourceDescriptor.manifests.find((m) => m.file === journal.groupManifest);
176
+ if (!declared)
177
+ throw Error("Unregistered original manifest");
178
+ const bytes = inside(first.packageRoot, declared.file), manifest = processGroupManifestSchema.parse(JSON.parse(bytes.toString()));
179
+ sourceResourceSha256 = sha256(bytes);
180
+ const contract = processGroupJournalContract(processGroupSourceIdentity(context(first).channels[1]), journal, manifest.profiles);
181
+ reference = {
182
+ directory: old.directory,
183
+ journalId: old.journalId,
184
+ journalContractSha256: sha256(contract),
185
+ generationId: manifest.id,
186
+ contractVersion: 1,
187
+ maxRecords: journal.maxRecords,
188
+ maxBytes: journal.maxBytes,
189
+ minFreeBytes: journal.minFreeBytes,
190
+ profiles: manifest.profiles.map(({ processName, mappingSha256, dataGroup }) => ({ processName, mappingSha256, dataGroup })),
191
+ };
192
+ }
193
+ const journal = retiredJournalReferenceSchema.parse(reference);
194
+ if (sourceResourceSha256 !== direct.resourceSha256 || hash(journal.profiles) !== hash(direct.profiles))
195
+ throw Error("Direct profile resources, paths or units changed");
196
+ const usage = inspectGenerationJournal(journal); // Pending work is allowed at preview, never at policy switch.
197
+ if (!Buffer.from(sourcePolicy.toString(), "utf8").equals(sourcePolicy))
198
+ throw Error("Original policy encoding cannot be retained exactly");
199
+ const member = (placement, c) => ({
200
+ placement,
201
+ processName: String(c.raw["uns"]["processName"]),
202
+ configurationSha256: hash(c.raw),
203
+ artifactSha256: groupArtifactHash(c.packageRoot),
204
+ });
205
+ const policy = processGroupRetirementPolicySchema.parse({
206
+ schemaVersion: 5,
207
+ kind: "uns-process-group-direct-retirement",
208
+ protocolVersion: 1,
209
+ operationId,
210
+ packageName: pkg(first).name,
211
+ namespace,
212
+ groupId: old.groupId,
213
+ controllerName: owner,
214
+ stateRoot,
215
+ recovery: "open",
216
+ journal,
217
+ sourcePolicyJson: sourcePolicy.toString(),
218
+ sourcePolicySha256: sha256(sourcePolicy),
219
+ source: {
220
+ publisher: {
221
+ ...member(input.source.publisher, first),
222
+ policyConfigurationSha256: sourceDescriptor.protocolVersion === 2 ? configurationResourceHash(first.raw) : hash(first.raw),
223
+ },
224
+ receiver: {
225
+ ...member(input.source.receiver, configs.source.receiver),
226
+ policyConfigurationSha256: sourceDescriptor.protocolVersion === 2 ? configurationResourceHash(configs.source.receiver.raw) : hash(configs.source.receiver.raw),
227
+ },
228
+ },
229
+ target: {
230
+ ...member(input.target, target),
231
+ packageRoot: target.packageRoot,
232
+ descriptorSha256: hash(d),
233
+ resourceSha256: direct.resourceSha256,
234
+ channelsSha256: channels,
235
+ },
236
+ });
237
+ if (sha256(read(old.file, true)) !== policy.sourcePolicySha256)
238
+ throw Error("Original policy changed during direct review");
239
+ const targetPolicy = Buffer.from(JSON.stringify(policy));
240
+ if (targetPolicy.length > 65536)
241
+ throw Error("Retirement policy byte budget exceeded");
242
+ return {
243
+ review: {
244
+ protocolVersion: 1,
245
+ kind: "paired-to-direct",
246
+ input,
247
+ operationId,
248
+ policyFile: old.file,
249
+ sourcePolicySha256: sha256(sourcePolicy),
250
+ targetPolicySha256: sha256(targetPolicy),
251
+ journal,
252
+ source: policy.source,
253
+ target: policy.target,
254
+ namespace,
255
+ groupId: old.groupId,
256
+ delivery: { inputPausePossible: true, exactlyOnceOutput: false, brokerReplayNotTransferred: true },
257
+ usage,
258
+ },
259
+ sourcePolicy,
260
+ targetPolicy,
261
+ };
262
+ }
263
+ //# sourceMappingURL=process-group-direct-review.js.map