@uns-kit/core 3.0.27 → 3.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATIONS.md +122 -0
- package/README.md +10 -0
- package/dist/config/app-config.d.ts +14 -0
- package/dist/config/app-config.d.ts.map +1 -1
- package/dist/config/app-config.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/configuration-group-authorization.d.ts +50 -0
- package/dist/runtime/configuration-group-authorization.d.ts.map +1 -0
- package/dist/runtime/configuration-group-authorization.js +113 -0
- package/dist/runtime/configuration-group-authorization.js.map +1 -0
- package/dist/runtime/configuration-group-contract.d.ts +75 -0
- package/dist/runtime/configuration-group-contract.d.ts.map +1 -0
- package/dist/runtime/configuration-group-contract.js +233 -0
- package/dist/runtime/configuration-group-contract.js.map +1 -0
- package/dist/runtime/process-group-authorization.d.ts +6 -0
- package/dist/runtime/process-group-authorization.d.ts.map +1 -1
- package/dist/runtime/process-group-authorization.js +56 -16
- package/dist/runtime/process-group-authorization.js.map +1 -1
- package/dist/runtime/process-group-backup-contract.d.ts +22 -0
- package/dist/runtime/process-group-backup-contract.d.ts.map +1 -0
- package/dist/runtime/process-group-backup-contract.js +20 -0
- package/dist/runtime/process-group-backup-contract.js.map +1 -0
- package/dist/runtime/process-group-backup-contract.json +7 -0
- package/dist/runtime/process-group-configured-upgrade.d.ts +4 -0
- package/dist/runtime/process-group-configured-upgrade.d.ts.map +1 -0
- package/dist/runtime/process-group-configured-upgrade.js +107 -0
- package/dist/runtime/process-group-configured-upgrade.js.map +1 -0
- package/dist/runtime/process-group-generation.d.ts +166 -0
- package/dist/runtime/process-group-generation.d.ts.map +1 -0
- package/dist/runtime/process-group-generation.js +278 -0
- package/dist/runtime/process-group-generation.js.map +1 -0
- package/dist/runtime/process-group-inspection.d.ts +2 -0
- package/dist/runtime/process-group-inspection.d.ts.map +1 -1
- package/dist/runtime/process-group-inspection.js +120 -40
- package/dist/runtime/process-group-inspection.js.map +1 -1
- package/dist/runtime/process-group-resources.d.ts +1 -0
- package/dist/runtime/process-group-resources.d.ts.map +1 -1
- package/dist/runtime/process-group-resources.js +8 -0
- package/dist/runtime/process-group-resources.js.map +1 -1
- package/dist/runtime/process-group-runtime-selection.d.ts +14 -0
- package/dist/runtime/process-group-runtime-selection.d.ts.map +1 -0
- package/dist/runtime/process-group-runtime-selection.js +29 -0
- package/dist/runtime/process-group-runtime-selection.js.map +1 -0
- package/dist/runtime/process-group-snapshot.mjs +60 -8
- package/dist/runtime/process-group-staging.d.ts +2 -2
- package/dist/runtime/process-group-staging.d.ts.map +1 -1
- package/dist/runtime/process-group-staging.js +6 -4
- package/dist/runtime/process-group-staging.js.map +1 -1
- package/dist/runtime/process-group-supervision.d.ts +2 -2
- package/dist/runtime/process-group-supervision.d.ts.map +1 -1
- package/dist/runtime/process-group-supervision.js +5 -3
- package/dist/runtime/process-group-supervision.js.map +1 -1
- package/dist/runtime/process-group-upgrade.d.ts +195 -0
- package/dist/runtime/process-group-upgrade.d.ts.map +1 -0
- package/dist/runtime/process-group-upgrade.js +262 -0
- package/dist/runtime/process-group-upgrade.js.map +1 -0
- package/dist/uns/uns-interfaces.d.ts +3 -0
- package/dist/uns/uns-interfaces.d.ts.map +1 -1
- package/dist/uns/uns-interfaces.js.map +1 -1
- package/dist/uns/uns-proxy-process.d.ts.map +1 -1
- package/dist/uns/uns-proxy-process.js +3 -0
- package/dist/uns/uns-proxy-process.js.map +1 -1
- package/dist/uns-config/config-schema.d.ts +16 -0
- package/dist/uns-config/config-schema.d.ts.map +1 -1
- package/dist/uns-config/mqtt-channel.d.ts +1 -1
- package/dist/uns-config/mqtt-channel.d.ts.map +1 -1
- package/dist/uns-config/mqtt-channel.js +3 -0
- package/dist/uns-config/mqtt-channel.js.map +1 -1
- package/dist/uns-config/uns-core-schema.d.ts +137 -0
- package/dist/uns-config/uns-core-schema.d.ts.map +1 -1
- package/dist/uns-config/uns-core-schema.js +6 -1
- package/dist/uns-config/uns-core-schema.js.map +1 -1
- package/dist/uns-mqtt/mqtt-interfaces.d.ts +5 -0
- package/dist/uns-mqtt/mqtt-interfaces.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-interfaces.js.map +1 -1
- package/dist/uns-mqtt/mqtt-proxy.d.ts +3 -0
- package/dist/uns-mqtt/mqtt-proxy.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-proxy.js +26 -1
- package/dist/uns-mqtt/mqtt-proxy.js.map +1 -1
- package/dist/uns-mqtt/mqtt-worker.d.ts +3 -1
- package/dist/uns-mqtt/mqtt-worker.d.ts.map +1 -1
- package/dist/uns-mqtt/mqtt-worker.js +45 -8
- package/dist/uns-mqtt/mqtt-worker.js.map +1 -1
- package/dist/uns-mqtt/publish-queue-contract.d.ts +33 -0
- package/dist/uns-mqtt/publish-queue-contract.d.ts.map +1 -0
- package/dist/uns-mqtt/publish-queue-contract.js +18 -0
- package/dist/uns-mqtt/publish-queue-contract.js.map +1 -0
- package/dist/uns-mqtt/publish-queue-store.d.ts +33 -0
- package/dist/uns-mqtt/publish-queue-store.d.ts.map +1 -0
- package/dist/uns-mqtt/publish-queue-store.js +177 -0
- package/dist/uns-mqtt/publish-queue-store.js.map +1 -0
- package/dist/uns-mqtt/publish-queue.d.ts +43 -0
- package/dist/uns-mqtt/publish-queue.d.ts.map +1 -0
- package/dist/uns-mqtt/publish-queue.js +235 -0
- package/dist/uns-mqtt/publish-queue.js.map +1 -0
- package/dist/uns-mqtt/uns-mqtt-proxy.d.ts +7 -0
- package/dist/uns-mqtt/uns-mqtt-proxy.d.ts.map +1 -1
- package/dist/uns-mqtt/uns-mqtt-proxy.js +98 -5
- package/dist/uns-mqtt/uns-mqtt-proxy.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { readConfigurationSelector } from "./process-group-contract.js";
|
|
6
|
+
import { readProcessGroupResource } from "./process-group-resources.js";
|
|
7
|
+
const identity = z.string().regex(/^[a-z][a-z0-9-]{0,99}$/);
|
|
8
|
+
const digest = z.string().regex(/^[a-f0-9]{64}$/);
|
|
9
|
+
const selector = z
|
|
10
|
+
.array(z
|
|
11
|
+
.string()
|
|
12
|
+
.regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,99}$/)
|
|
13
|
+
.refine((v) => !["__proto__", "prototype", "constructor"].includes(v)))
|
|
14
|
+
.min(1)
|
|
15
|
+
.max(8);
|
|
16
|
+
const MAX_BYTES = 1024 * 1024;
|
|
17
|
+
/** Versioned canonical JSON: binary key order, no locale, executable values or accessors. */
|
|
18
|
+
export function configurationResourceJson(value) {
|
|
19
|
+
let nodes = 0, bytes = 0;
|
|
20
|
+
const ancestors = new Set();
|
|
21
|
+
const charge = (size) => {
|
|
22
|
+
bytes += size;
|
|
23
|
+
if (bytes > MAX_BYTES)
|
|
24
|
+
throw Error("Configuration resource exceeds 1 MiB");
|
|
25
|
+
};
|
|
26
|
+
function visit(v, depth) {
|
|
27
|
+
if (++nodes > 65536 || depth > 32)
|
|
28
|
+
throw Error("Configuration resource exceeds its structural budget");
|
|
29
|
+
if (v === null || typeof v === "boolean") {
|
|
30
|
+
charge(v === null ? 4 : v ? 4 : 5);
|
|
31
|
+
return JSON.stringify(v);
|
|
32
|
+
}
|
|
33
|
+
if (typeof v === "string") {
|
|
34
|
+
if (Buffer.byteLength(v) > MAX_BYTES)
|
|
35
|
+
throw Error("Configuration resource string exceeds 1 MiB");
|
|
36
|
+
const encoded = JSON.stringify(v);
|
|
37
|
+
charge(Buffer.byteLength(encoded));
|
|
38
|
+
return encoded;
|
|
39
|
+
}
|
|
40
|
+
if (typeof v === "number" && Number.isFinite(v)) {
|
|
41
|
+
const encoded = JSON.stringify(v);
|
|
42
|
+
charge(encoded.length);
|
|
43
|
+
return encoded;
|
|
44
|
+
}
|
|
45
|
+
if (!v || typeof v !== "object" || ancestors.has(v))
|
|
46
|
+
throw Error("Configuration resource must contain finite plain JSON only");
|
|
47
|
+
if (Array.isArray(v)
|
|
48
|
+
? Object.getPrototypeOf(v) !== Array.prototype
|
|
49
|
+
: Object.getPrototypeOf(v) !== Object.prototype && Object.getPrototypeOf(v) !== null)
|
|
50
|
+
throw Error("Configuration resource must contain plain JSON objects");
|
|
51
|
+
if (Object.getOwnPropertySymbols(v).length)
|
|
52
|
+
throw Error("Configuration resource cannot contain symbol properties");
|
|
53
|
+
const descriptors = Object.getOwnPropertyDescriptors(v);
|
|
54
|
+
for (const [key, d] of Object.entries(descriptors)) {
|
|
55
|
+
if (Array.isArray(v) && key === "length")
|
|
56
|
+
continue;
|
|
57
|
+
if (!d.enumerable || !Object.hasOwn(d, "value"))
|
|
58
|
+
throw Error("Configuration resource cannot contain hidden properties or accessors");
|
|
59
|
+
}
|
|
60
|
+
ancestors.add(v);
|
|
61
|
+
charge(2); // Container brackets/braces.
|
|
62
|
+
let result;
|
|
63
|
+
if (Array.isArray(v)) {
|
|
64
|
+
if (v.length > 65536 || Object.keys(v).length !== v.length || Object.keys(v).some((k, i) => k !== String(i)))
|
|
65
|
+
throw Error("Configuration resource arrays must be dense JSON arrays");
|
|
66
|
+
charge(Math.max(0, v.length - 1));
|
|
67
|
+
result = "[" + Array.from({ length: v.length }, (_, i) => visit(descriptors[String(i)].value, depth + 1)).join(",") + "]";
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
result =
|
|
71
|
+
"{" +
|
|
72
|
+
Object.keys(v)
|
|
73
|
+
.sort()
|
|
74
|
+
.map((k, i) => {
|
|
75
|
+
if (Buffer.byteLength(k) > MAX_BYTES)
|
|
76
|
+
throw Error("Configuration resource key exceeds 1 MiB");
|
|
77
|
+
charge(Buffer.byteLength(JSON.stringify(k)) + 1 + (i ? 1 : 0));
|
|
78
|
+
return JSON.stringify(k) + ":" + visit(descriptors[k].value, depth + 1);
|
|
79
|
+
})
|
|
80
|
+
.join(",") +
|
|
81
|
+
"}";
|
|
82
|
+
ancestors.delete(v);
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
const json = visit(value, 0);
|
|
86
|
+
if (Buffer.byteLength(json) > MAX_BYTES)
|
|
87
|
+
throw Error("Configuration resource exceeds 1 MiB");
|
|
88
|
+
return json;
|
|
89
|
+
}
|
|
90
|
+
export function configurationResourceHash(value) {
|
|
91
|
+
return createHash("sha256").update("uns-configuration-json-v1\n").update(configurationResourceJson(value)).digest("hex");
|
|
92
|
+
}
|
|
93
|
+
export const configurationGroupProfileSchema = z.strictObject({
|
|
94
|
+
id: identity,
|
|
95
|
+
processName: identity,
|
|
96
|
+
dataGroup: identity,
|
|
97
|
+
resource: z.unknown(),
|
|
98
|
+
});
|
|
99
|
+
export const configurationGroupSchema = z.strictObject({
|
|
100
|
+
schemaVersion: z.literal(2),
|
|
101
|
+
id: identity,
|
|
102
|
+
inputTopic: z
|
|
103
|
+
.string()
|
|
104
|
+
.min(1)
|
|
105
|
+
.max(512)
|
|
106
|
+
.regex(/^[^#+\0]+$/),
|
|
107
|
+
processName: identity,
|
|
108
|
+
receiverProcessName: identity,
|
|
109
|
+
profiles: z.array(configurationGroupProfileSchema).min(2).max(16),
|
|
110
|
+
});
|
|
111
|
+
export const configurationGroupDescriptorSchema = z
|
|
112
|
+
.strictObject({
|
|
113
|
+
protocolVersion: z.literal(2),
|
|
114
|
+
namespace: identity,
|
|
115
|
+
publisherPath: selector,
|
|
116
|
+
groupPath: selector,
|
|
117
|
+
memberPath: selector,
|
|
118
|
+
journalPath: selector,
|
|
119
|
+
runtimeRolePath: selector,
|
|
120
|
+
receiverRole: identity,
|
|
121
|
+
match: z.strictObject({ path: selector, value: z.string().min(1).max(100) }).optional(),
|
|
122
|
+
})
|
|
123
|
+
.superRefine((d, context) => {
|
|
124
|
+
const independent = [d.publisherPath, d.journalPath, d.runtimeRolePath].map((p) => p.join("."));
|
|
125
|
+
if (new Set(independent).size !== independent.length || independent.some((p, i) => independent.some((q, j) => i !== j && q.startsWith(p + "."))))
|
|
126
|
+
context.addIssue({ code: "custom", message: "Independent publisher, journal and role selectors required" });
|
|
127
|
+
const parent = d.publisherPath.join(".") + ".", group = d.groupPath.join("."), member = d.memberPath.join(".");
|
|
128
|
+
if (!group.startsWith(parent) ||
|
|
129
|
+
!member.startsWith(parent) ||
|
|
130
|
+
group === member ||
|
|
131
|
+
group.startsWith(member + ".") ||
|
|
132
|
+
member.startsWith(group + "."))
|
|
133
|
+
context.addIssue({ code: "custom", message: "Distinct group/member selectors within the publisher required" });
|
|
134
|
+
});
|
|
135
|
+
const snapshots = new WeakSet();
|
|
136
|
+
function freeze(value) {
|
|
137
|
+
if (value && typeof value === "object") {
|
|
138
|
+
for (const child of Object.values(value))
|
|
139
|
+
freeze(child);
|
|
140
|
+
Object.freeze(value);
|
|
141
|
+
}
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
export function configurationGroupSnapshot(value) {
|
|
145
|
+
// Bound and copy before schema traversal; caller mutation cannot change a running revision.
|
|
146
|
+
const group = configurationGroupSchema.parse(JSON.parse(configurationResourceJson(value)));
|
|
147
|
+
const names = [group.processName, group.receiverProcessName, ...group.profiles.map((p) => p.processName)];
|
|
148
|
+
if (new Set(names).size !== names.length || new Set(group.profiles.map((p) => p.id)).size !== group.profiles.length)
|
|
149
|
+
throw Error("Configuration group identities overlap");
|
|
150
|
+
const profiles = group.profiles.map((p) => ({ ...p, resourceSha256: configurationResourceHash(p.resource) }));
|
|
151
|
+
const result = freeze({ group, sha256: configurationResourceHash(group), profiles });
|
|
152
|
+
snapshots.add(result);
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
export function assertConfigurationGroupSnapshot(value) {
|
|
156
|
+
if (!snapshots.has(value))
|
|
157
|
+
throw Error("Exact SDK-issued configuration group snapshot required");
|
|
158
|
+
}
|
|
159
|
+
/** Optional data-only capability; packages without it keep their existing behavior. */
|
|
160
|
+
export function configurationGroupDescriptor(packageRoot) {
|
|
161
|
+
const file = path.join(packageRoot, "package.json");
|
|
162
|
+
// Ordinary Node/Python deployments do not opt in by existing on the host.
|
|
163
|
+
if (!fs.existsSync(file))
|
|
164
|
+
return undefined;
|
|
165
|
+
const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
166
|
+
let bytes;
|
|
167
|
+
try {
|
|
168
|
+
const stat = fs.fstatSync(fd);
|
|
169
|
+
if (!stat.isFile() || stat.size > MAX_BYTES)
|
|
170
|
+
throw Error("Invalid installed runtime metadata");
|
|
171
|
+
bytes = fs.readFileSync(fd);
|
|
172
|
+
if (bytes.length > MAX_BYTES)
|
|
173
|
+
throw Error("Installed runtime metadata is too large");
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
fs.closeSync(fd);
|
|
177
|
+
}
|
|
178
|
+
const pkg = JSON.parse(bytes.toString());
|
|
179
|
+
const value = pkg.unsDatahub?.processGroupConfigurationRuntime;
|
|
180
|
+
if (value !== undefined && !readProcessGroupResource(file).equals(bytes))
|
|
181
|
+
throw Error("Installed runtime metadata changed during discovery");
|
|
182
|
+
return value === undefined ? undefined : configurationGroupDescriptorSchema.parse(value);
|
|
183
|
+
}
|
|
184
|
+
export function selectedConfigurationGroup(packageRoot, raw) {
|
|
185
|
+
const descriptor = configurationGroupDescriptor(packageRoot);
|
|
186
|
+
if (!descriptor)
|
|
187
|
+
return undefined;
|
|
188
|
+
const value = readConfigurationSelector(raw, descriptor.groupPath);
|
|
189
|
+
if (value === undefined)
|
|
190
|
+
return undefined;
|
|
191
|
+
if (descriptor.match && readConfigurationSelector(raw, descriptor.match.path) !== descriptor.match.value)
|
|
192
|
+
throw Error("Configuration group capability selector does not match");
|
|
193
|
+
return { descriptor, snapshot: configurationGroupSnapshot(value) };
|
|
194
|
+
}
|
|
195
|
+
export const configurationGroupJournalSchema = z.strictObject({
|
|
196
|
+
directory: z.string().startsWith("/").max(512),
|
|
197
|
+
journalId: z.string().uuid().optional(),
|
|
198
|
+
generationId: identity,
|
|
199
|
+
groupSha256: digest,
|
|
200
|
+
minFreeBytes: z
|
|
201
|
+
.number()
|
|
202
|
+
.int()
|
|
203
|
+
.min(1024 * 1024)
|
|
204
|
+
.max(1024 * 1024 * 1024)
|
|
205
|
+
.default(64 * 1024 * 1024),
|
|
206
|
+
maxRecords: z.number().int().min(1).max(100000).default(20000),
|
|
207
|
+
maxBytes: z
|
|
208
|
+
.number()
|
|
209
|
+
.int()
|
|
210
|
+
.min(1024)
|
|
211
|
+
.max(256 * 1024 * 1024)
|
|
212
|
+
.default(32 * 1024 * 1024),
|
|
213
|
+
});
|
|
214
|
+
export function configurationGroupJournalContract(snapshot, sourceIdentity, config, profiles) {
|
|
215
|
+
assertConfigurationGroupSnapshot(snapshot);
|
|
216
|
+
const journal = configurationGroupJournalSchema.parse(config);
|
|
217
|
+
if (journal.groupSha256 !== snapshot.sha256 || !digest.safeParse(sourceIdentity).success)
|
|
218
|
+
throw Error("Configuration group journal revision differs");
|
|
219
|
+
const expected = snapshot.profiles.map(({ processName, resourceSha256, dataGroup }) => ({ processName, resourceSha256, dataGroup }));
|
|
220
|
+
const normalize = (v) => [...v].sort((a, b) => (a.processName < b.processName ? -1 : a.processName > b.processName ? 1 : 0));
|
|
221
|
+
if (configurationResourceHash(normalize([...profiles])) !== configurationResourceHash(normalize(expected)))
|
|
222
|
+
throw Error("Configuration group journal profiles differ");
|
|
223
|
+
return configurationResourceJson({
|
|
224
|
+
version: 2,
|
|
225
|
+
generationId: journal.generationId,
|
|
226
|
+
groupSha256: snapshot.sha256,
|
|
227
|
+
sourceIdentity,
|
|
228
|
+
maxRecords: journal.maxRecords,
|
|
229
|
+
maxBytes: journal.maxBytes,
|
|
230
|
+
profiles: normalize(expected),
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=configuration-group-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuration-group-contract.js","sourceRoot":"","sources":["../../src/runtime/configuration-group-contract.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\n\nimport { readConfigurationSelector } from \"./process-group-contract.js\";\nimport { readProcessGroupResource } from \"./process-group-resources.js\";\n\nconst identity = z.string().regex(/^[a-z][a-z0-9-]{0,99}$/);\nconst digest = z.string().regex(/^[a-f0-9]{64}$/);\nconst selector = z\n .array(\n z\n .string()\n .regex(/^[a-zA-Z][a-zA-Z0-9_-]{0,99}$/)\n .refine((v) => ![\"__proto__\", \"prototype\", \"constructor\"].includes(v)),\n )\n .min(1)\n .max(8);\nconst MAX_BYTES = 1024 * 1024;\n\n/** Versioned canonical JSON: binary key order, no locale, executable values or accessors. */\nexport function configurationResourceJson(value: unknown): string {\n let nodes = 0,\n bytes = 0;\n const ancestors = new Set<object>();\n const charge = (size: number) => {\n bytes += size;\n if (bytes > MAX_BYTES) throw Error(\"Configuration resource exceeds 1 MiB\");\n };\n function visit(v: unknown, depth: number): string {\n if (++nodes > 65536 || depth > 32) throw Error(\"Configuration resource exceeds its structural budget\");\n if (v === null || typeof v === \"boolean\") {\n charge(v === null ? 4 : v ? 4 : 5);\n return JSON.stringify(v);\n }\n if (typeof v === \"string\") {\n if (Buffer.byteLength(v) > MAX_BYTES) throw Error(\"Configuration resource string exceeds 1 MiB\");\n const encoded = JSON.stringify(v);\n charge(Buffer.byteLength(encoded));\n return encoded;\n }\n if (typeof v === \"number\" && Number.isFinite(v)) {\n const encoded = JSON.stringify(v);\n charge(encoded.length);\n return encoded;\n }\n if (!v || typeof v !== \"object\" || ancestors.has(v)) throw Error(\"Configuration resource must contain finite plain JSON only\");\n if (\n Array.isArray(v)\n ? Object.getPrototypeOf(v) !== Array.prototype\n : Object.getPrototypeOf(v) !== Object.prototype && Object.getPrototypeOf(v) !== null\n )\n throw Error(\"Configuration resource must contain plain JSON objects\");\n if (Object.getOwnPropertySymbols(v).length) throw Error(\"Configuration resource cannot contain symbol properties\");\n const descriptors = Object.getOwnPropertyDescriptors(v);\n for (const [key, d] of Object.entries(descriptors)) {\n if (Array.isArray(v) && key === \"length\") continue;\n if (!d.enumerable || !Object.hasOwn(d, \"value\")) throw Error(\"Configuration resource cannot contain hidden properties or accessors\");\n }\n ancestors.add(v);\n charge(2); // Container brackets/braces.\n let result: string;\n if (Array.isArray(v)) {\n if (v.length > 65536 || Object.keys(v).length !== v.length || Object.keys(v).some((k, i) => k !== String(i)))\n throw Error(\"Configuration resource arrays must be dense JSON arrays\");\n charge(Math.max(0, v.length - 1));\n result = \"[\" + Array.from({ length: v.length }, (_, i) => visit(descriptors[String(i)]!.value, depth + 1)).join(\",\") + \"]\";\n } else\n result =\n \"{\" +\n Object.keys(v)\n .sort()\n .map((k, i) => {\n if (Buffer.byteLength(k) > MAX_BYTES) throw Error(\"Configuration resource key exceeds 1 MiB\");\n charge(Buffer.byteLength(JSON.stringify(k)) + 1 + (i ? 1 : 0));\n return JSON.stringify(k) + \":\" + visit(descriptors[k]!.value, depth + 1);\n })\n .join(\",\") +\n \"}\";\n ancestors.delete(v);\n return result;\n }\n const json = visit(value, 0);\n if (Buffer.byteLength(json) > MAX_BYTES) throw Error(\"Configuration resource exceeds 1 MiB\");\n return json;\n}\n\nexport function configurationResourceHash(value: unknown): string {\n return createHash(\"sha256\").update(\"uns-configuration-json-v1\\n\").update(configurationResourceJson(value)).digest(\"hex\");\n}\n\nexport const configurationGroupProfileSchema = z.strictObject({\n id: identity,\n processName: identity,\n dataGroup: identity,\n resource: z.unknown(),\n});\nexport const configurationGroupSchema = z.strictObject({\n schemaVersion: z.literal(2),\n id: identity,\n inputTopic: z\n .string()\n .min(1)\n .max(512)\n .regex(/^[^#+\\0]+$/),\n processName: identity,\n receiverProcessName: identity,\n profiles: z.array(configurationGroupProfileSchema).min(2).max(16),\n});\nexport const configurationGroupDescriptorSchema = z\n .strictObject({\n protocolVersion: z.literal(2),\n namespace: identity,\n publisherPath: selector,\n groupPath: selector,\n memberPath: selector,\n journalPath: selector,\n runtimeRolePath: selector,\n receiverRole: identity,\n match: z.strictObject({ path: selector, value: z.string().min(1).max(100) }).optional(),\n })\n .superRefine((d, context) => {\n const independent = [d.publisherPath, d.journalPath, d.runtimeRolePath].map((p) => p.join(\".\"));\n if (new Set(independent).size !== independent.length || independent.some((p, i) => independent.some((q, j) => i !== j && q.startsWith(p + \".\"))))\n context.addIssue({ code: \"custom\", message: \"Independent publisher, journal and role selectors required\" });\n const parent = d.publisherPath.join(\".\") + \".\",\n group = d.groupPath.join(\".\"),\n member = d.memberPath.join(\".\");\n if (\n !group.startsWith(parent) ||\n !member.startsWith(parent) ||\n group === member ||\n group.startsWith(member + \".\") ||\n member.startsWith(group + \".\")\n )\n context.addIssue({ code: \"custom\", message: \"Distinct group/member selectors within the publisher required\" });\n });\nexport type ConfigurationGroupDescriptor = z.infer<typeof configurationGroupDescriptorSchema>;\nexport type ConfigurationGroup = z.infer<typeof configurationGroupSchema>;\nexport interface ConfigurationGroupProfile {\n readonly id: string;\n readonly processName: string;\n readonly dataGroup: string;\n readonly resourceSha256: string;\n readonly resource: unknown;\n}\nexport interface ConfigurationGroupSnapshot {\n readonly group: Readonly<ConfigurationGroup>;\n readonly sha256: string;\n readonly profiles: readonly ConfigurationGroupProfile[];\n}\nconst snapshots = new WeakSet<object>();\nfunction freeze<T>(value: T): T {\n if (value && typeof value === \"object\") {\n for (const child of Object.values(value)) freeze(child);\n Object.freeze(value);\n }\n return value;\n}\nexport function configurationGroupSnapshot(value: unknown): ConfigurationGroupSnapshot {\n // Bound and copy before schema traversal; caller mutation cannot change a running revision.\n const group = configurationGroupSchema.parse(JSON.parse(configurationResourceJson(value)));\n const names = [group.processName, group.receiverProcessName, ...group.profiles.map((p) => p.processName)];\n if (new Set(names).size !== names.length || new Set(group.profiles.map((p) => p.id)).size !== group.profiles.length)\n throw Error(\"Configuration group identities overlap\");\n const profiles = group.profiles.map((p) => ({ ...p, resourceSha256: configurationResourceHash(p.resource) }));\n const result = freeze({ group, sha256: configurationResourceHash(group), profiles });\n snapshots.add(result);\n return result;\n}\nexport function assertConfigurationGroupSnapshot(value: ConfigurationGroupSnapshot): void {\n if (!snapshots.has(value)) throw Error(\"Exact SDK-issued configuration group snapshot required\");\n}\n\n/** Optional data-only capability; packages without it keep their existing behavior. */\nexport function configurationGroupDescriptor(packageRoot: string): ConfigurationGroupDescriptor | undefined {\n const file = path.join(packageRoot, \"package.json\");\n // Ordinary Node/Python deployments do not opt in by existing on the host.\n if (!fs.existsSync(file)) return undefined;\n const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);\n let bytes: Buffer;\n try {\n const stat = fs.fstatSync(fd);\n if (!stat.isFile() || stat.size > MAX_BYTES) throw Error(\"Invalid installed runtime metadata\");\n bytes = fs.readFileSync(fd);\n if (bytes.length > MAX_BYTES) throw Error(\"Installed runtime metadata is too large\");\n } finally {\n fs.closeSync(fd);\n }\n const pkg = JSON.parse(bytes.toString());\n const value = pkg.unsDatahub?.processGroupConfigurationRuntime;\n if (value !== undefined && !readProcessGroupResource(file).equals(bytes)) throw Error(\"Installed runtime metadata changed during discovery\");\n return value === undefined ? undefined : configurationGroupDescriptorSchema.parse(value);\n}\nexport function selectedConfigurationGroup(\n packageRoot: string,\n raw: Record<string, unknown>,\n):\n | {\n descriptor: ConfigurationGroupDescriptor;\n snapshot: ConfigurationGroupSnapshot;\n }\n | undefined {\n const descriptor = configurationGroupDescriptor(packageRoot);\n if (!descriptor) return undefined;\n const value = readConfigurationSelector(raw, descriptor.groupPath);\n if (value === undefined) return undefined;\n if (descriptor.match && readConfigurationSelector(raw, descriptor.match.path) !== descriptor.match.value)\n throw Error(\"Configuration group capability selector does not match\");\n return { descriptor, snapshot: configurationGroupSnapshot(value) };\n}\n\nexport const configurationGroupJournalSchema = z.strictObject({\n directory: z.string().startsWith(\"/\").max(512),\n journalId: z.string().uuid().optional(),\n generationId: identity,\n groupSha256: digest,\n minFreeBytes: z\n .number()\n .int()\n .min(1024 * 1024)\n .max(1024 * 1024 * 1024)\n .default(64 * 1024 * 1024),\n maxRecords: z.number().int().min(1).max(100000).default(20000),\n maxBytes: z\n .number()\n .int()\n .min(1024)\n .max(256 * 1024 * 1024)\n .default(32 * 1024 * 1024),\n});\nexport type ConfigurationGroupJournal = z.infer<typeof configurationGroupJournalSchema>;\nexport function configurationGroupJournalContract(\n snapshot: ConfigurationGroupSnapshot,\n sourceIdentity: string,\n config: ConfigurationGroupJournal,\n profiles: readonly { processName: string; resourceSha256: string; dataGroup: string }[],\n): string {\n assertConfigurationGroupSnapshot(snapshot);\n const journal = configurationGroupJournalSchema.parse(config);\n if (journal.groupSha256 !== snapshot.sha256 || !digest.safeParse(sourceIdentity).success)\n throw Error(\"Configuration group journal revision differs\");\n const expected = snapshot.profiles.map(({ processName, resourceSha256, dataGroup }) => ({ processName, resourceSha256, dataGroup }));\n const normalize = (v: typeof expected) => [...v].sort((a, b) => (a.processName < b.processName ? -1 : a.processName > b.processName ? 1 : 0));\n if (configurationResourceHash(normalize([...profiles])) !== configurationResourceHash(normalize(expected)))\n throw Error(\"Configuration group journal profiles differ\");\n return configurationResourceJson({\n version: 2,\n generationId: journal.generationId,\n groupSha256: snapshot.sha256,\n sourceIdentity,\n maxRecords: journal.maxRecords,\n maxBytes: journal.maxBytes,\n profiles: normalize(expected),\n });\n}\n"]}
|
|
@@ -52,6 +52,8 @@ interface GenericAuthorization {
|
|
|
52
52
|
readonly groupId: string;
|
|
53
53
|
readonly groupProcessName: string;
|
|
54
54
|
readonly namespace: string;
|
|
55
|
+
readonly generationId?: string;
|
|
56
|
+
readonly configurationGroupSha256?: string;
|
|
55
57
|
}
|
|
56
58
|
export type ProcessGroupAuthorization = legacy.HvAuthorization | GenericAuthorization;
|
|
57
59
|
export type HvAuthorization = ProcessGroupAuthorization;
|
|
@@ -95,7 +97,11 @@ export interface ProcessGroupAuthorizationContext {
|
|
|
95
97
|
stateRoot?: string;
|
|
96
98
|
initialize?: boolean;
|
|
97
99
|
}
|
|
100
|
+
/** Live authority always comes from the current canonical private policy. */
|
|
98
101
|
export declare function authorizeProcessGroupRuntime(context: ProcessGroupAuthorizationContext): ProcessGroupAuthorization;
|
|
102
|
+
/** Review only: never issues an authorization accepted by runtime/launch checks. */
|
|
103
|
+
export declare function validateProcessGroupPolicyCandidate(context: ProcessGroupAuthorizationContext, bytes: Buffer): void;
|
|
104
|
+
export declare function processGroupAuthorizationFile(context: ProcessGroupAuthorizationContext): string;
|
|
99
105
|
export declare const authorizeHvRuntime: typeof authorizeProcessGroupRuntime;
|
|
100
106
|
export declare function authorizeConfiguredProcessGroupRuntime(pkg: string, dir: string, raw: Record<string, unknown>, controllerName: string, initialize?: boolean): ProcessGroupAuthorization;
|
|
101
107
|
export declare function assertProcessGroupJournalAuthorization(value: ProcessGroupAuthorization | undefined, directory: string, journalId: string | undefined): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-group-authorization.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-authorization.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,MAAM,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"process-group-authorization.d.ts","sourceRoot":"","sources":["../../src/runtime/process-group-authorization.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,9 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import * as legacy from "./compatibility/energenti-authorization-v1.js";
|
|
5
|
+
import { configurationGroupAuthorizationSchema, configurationGroupPolicyIdentity, verifyConfigurationGroupPolicy } from "./configuration-group-authorization.js";
|
|
5
6
|
import { normalizeProcessGroupConfiguration, processGroupDescriptor, resolvedProcessGroupChannels, } from "./process-group-contract.js";
|
|
6
|
-
import { configurationAuthorizationHash, groupArtifactHash, groupChannelsHash, readProcessGroupResource as read, sha256 as sha, } from "./process-group-resources.js";
|
|
7
|
+
import { configurationAuthorizationHash, groupArtifactHash, groupChannelsHash, readProcessGroupResource as read, sha256 as sha, assertPrivateProcessGroupDirectory, } from "./process-group-resources.js";
|
|
7
8
|
export { configurationAuthorizationHash, groupArtifactHash, groupChannelsHash } from "./process-group-resources.js";
|
|
8
9
|
export const hasProcessGroupAuthorization = legacy.hasProcessGroupAuthorization;
|
|
9
10
|
const digest = z.string().regex(/^[a-f0-9]{64}$/), id = z.string().regex(/^[a-z][a-z0-9-]{0,99}$/);
|
|
@@ -52,14 +53,7 @@ export const processGroupManifestSchema = z.strictObject({
|
|
|
52
53
|
export const hvAuthorizationSchema = legacy.hvAuthorizationSchema;
|
|
53
54
|
export const productionGroupIds = legacy.productionGroupIds;
|
|
54
55
|
const issued = new WeakSet();
|
|
55
|
-
|
|
56
|
-
for (let p = dir; p !== path.dirname(p); p = path.dirname(p))
|
|
57
|
-
if (fs.lstatSync(p).isSymbolicLink())
|
|
58
|
-
throw Error("Linked policy directory");
|
|
59
|
-
const s = fs.lstatSync(dir);
|
|
60
|
-
if (!s.isDirectory() || s.uid !== process.getuid?.() || (s.mode & 0o077) !== 0)
|
|
61
|
-
throw Error("Insecure policy directory");
|
|
62
|
-
}
|
|
56
|
+
const privateDirectory = assertPrivateProcessGroupDirectory;
|
|
63
57
|
function registryRoot(root, dir) {
|
|
64
58
|
if (!path.isAbsolute(root) || path.resolve(root) !== root || path.resolve(dir) !== dir)
|
|
65
59
|
throw Error("Invalid policy registry");
|
|
@@ -74,6 +68,24 @@ function registryRoot(root, dir) {
|
|
|
74
68
|
return relative.split("/")[0];
|
|
75
69
|
}
|
|
76
70
|
function selectedFile(pkg, raw, root, explicit) {
|
|
71
|
+
const configured = configurationGroupPolicyIdentity(pkg, raw);
|
|
72
|
+
if (configured) {
|
|
73
|
+
if (explicit)
|
|
74
|
+
return explicit;
|
|
75
|
+
const directory = process.env["UNS_PROCESS_GROUP_AUTHORIZATION_DIRECTORY"];
|
|
76
|
+
if (directory) {
|
|
77
|
+
const selected = registryRoot(root, directory);
|
|
78
|
+
if (selected !== "*" && selected !== configured.namespace)
|
|
79
|
+
throw Error("Foreign runtime registry");
|
|
80
|
+
const registry = selected === "*" ? path.join(root, configured.namespace, "authorizations") : directory;
|
|
81
|
+
privateDirectory(registry);
|
|
82
|
+
return path.join(registry, configured.generationId + ".json");
|
|
83
|
+
}
|
|
84
|
+
const single = process.env["UNS_PROCESS_GROUP_AUTHORIZATION_FILE"];
|
|
85
|
+
if (!single)
|
|
86
|
+
throw Error("No selected policy");
|
|
87
|
+
return single;
|
|
88
|
+
}
|
|
77
89
|
const descriptor = processGroupDescriptor(pkg);
|
|
78
90
|
if (!descriptor)
|
|
79
91
|
throw Error("Missing runtime contract");
|
|
@@ -175,10 +187,11 @@ export function configuredGroupProcessNames() {
|
|
|
175
187
|
const result = new Set();
|
|
176
188
|
for (const file of files) {
|
|
177
189
|
const raw = JSON.parse(read(file, true).toString());
|
|
178
|
-
const p = raw.schemaVersion === 3
|
|
190
|
+
const p = raw.schemaVersion === 4 ? configurationGroupAuthorizationSchema.parse(raw) : raw.schemaVersion === 3
|
|
179
191
|
? processGroupAuthorizationSchema.parse(raw)
|
|
180
192
|
: z.union([legacy.hvAuthorizationSchema, legacy.processGroupAuthorizationSchema]).parse(raw);
|
|
181
|
-
const { namespace, group } = p.schemaVersion ===
|
|
193
|
+
const { namespace, group } = p.schemaVersion === 4 ? { namespace: p.namespace, group: p.generationId }
|
|
194
|
+
: p.schemaVersion === 3 ? { namespace: p.namespace, group: p.groupId } : legacy.legacyPolicyIdentity(p);
|
|
182
195
|
if (p.stateRoot !== root ||
|
|
183
196
|
file !== path.join(root, namespace, "authorizations", group + ".json") ||
|
|
184
197
|
p.directory !== path.join(root, namespace, "admission", group))
|
|
@@ -194,14 +207,23 @@ export function configuredGroupProcessNames() {
|
|
|
194
207
|
throw Error("Process-group authorization registry is missing, changed or insecure; review required");
|
|
195
208
|
}
|
|
196
209
|
}
|
|
197
|
-
|
|
210
|
+
function verifyRuntimePolicy(context, candidate) {
|
|
198
211
|
try {
|
|
199
212
|
const root = context.stateRoot ?? process.env["UNS_PROCESS_GROUP_STATE_ROOT"];
|
|
200
213
|
if (!root || !context.controllerName)
|
|
201
214
|
throw Error();
|
|
202
|
-
const file = selectedFile(context.packageRoot, context.rawConfiguration, root, context.file), bytes = read(file, true), unparsed = JSON.parse(bytes.toString());
|
|
203
|
-
if (unparsed.schemaVersion
|
|
215
|
+
const file = selectedFile(context.packageRoot, context.rawConfiguration, root, context.file), bytes = candidate ?? read(file, true), unparsed = JSON.parse(bytes.toString());
|
|
216
|
+
if (unparsed.schemaVersion === 4) {
|
|
217
|
+
const result = verifyConfigurationGroupPolicy(context, bytes, root, file);
|
|
218
|
+
if (!candidate)
|
|
219
|
+
issued.add(result);
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
if (unparsed.schemaVersion !== 3) {
|
|
223
|
+
if (candidate)
|
|
224
|
+
throw Error("Only generic policies can be staged");
|
|
204
225
|
return legacy.authorizeHvRuntime({ ...context, file, stateRoot: root });
|
|
226
|
+
}
|
|
205
227
|
const p = processGroupAuthorizationSchema.parse(unparsed), d = processGroupDescriptor(context.packageRoot);
|
|
206
228
|
if (!d || d.legacy)
|
|
207
229
|
throw Error("Generic runtime descriptor required");
|
|
@@ -280,13 +302,28 @@ export function authorizeProcessGroupRuntime(context) {
|
|
|
280
302
|
groupProcessName: m.processName,
|
|
281
303
|
namespace: d.namespace,
|
|
282
304
|
});
|
|
283
|
-
|
|
305
|
+
if (!candidate)
|
|
306
|
+
issued.add(result);
|
|
284
307
|
return result;
|
|
285
308
|
}
|
|
286
309
|
catch {
|
|
287
310
|
throw Error("Process-group runtime authorization is missing, changed or does not match this installed placement; review required");
|
|
288
311
|
}
|
|
289
312
|
}
|
|
313
|
+
/** Live authority always comes from the current canonical private policy. */
|
|
314
|
+
export function authorizeProcessGroupRuntime(context) {
|
|
315
|
+
return verifyRuntimePolicy(context);
|
|
316
|
+
}
|
|
317
|
+
/** Review only: never issues an authorization accepted by runtime/launch checks. */
|
|
318
|
+
export function validateProcessGroupPolicyCandidate(context, bytes) {
|
|
319
|
+
verifyRuntimePolicy(context, bytes);
|
|
320
|
+
}
|
|
321
|
+
export function processGroupAuthorizationFile(context) {
|
|
322
|
+
const root = context.stateRoot ?? process.env["UNS_PROCESS_GROUP_STATE_ROOT"];
|
|
323
|
+
if (!root)
|
|
324
|
+
throw Error("Missing process-group state root");
|
|
325
|
+
return selectedFile(context.packageRoot, context.rawConfiguration, root, context.file);
|
|
326
|
+
}
|
|
290
327
|
export const authorizeHvRuntime = authorizeProcessGroupRuntime;
|
|
291
328
|
export function authorizeConfiguredProcessGroupRuntime(pkg, dir, raw, controllerName, initialize = false) {
|
|
292
329
|
return authorizeProcessGroupRuntime({
|
|
@@ -313,7 +350,7 @@ export function assertProcessGroupStateMount(value, root) {
|
|
|
313
350
|
return;
|
|
314
351
|
}
|
|
315
352
|
assertProcessGroupJournalAuthorization(value, value.directory, value.journalId ?? undefined);
|
|
316
|
-
if (process.platform !== "linux" || !("namespace" in value) || value.directory !== path.join(root, value.namespace, "admission", value.groupId))
|
|
353
|
+
if (process.platform !== "linux" || !("namespace" in value) || value.directory !== path.join(root, value.namespace, "admission", value.generationId ?? value.groupId))
|
|
317
354
|
throw Error("Process group requires its reviewed Linux state mount");
|
|
318
355
|
const mount = fs
|
|
319
356
|
.readFileSync("/proc/self/mountinfo", "utf8")
|
|
@@ -343,6 +380,9 @@ export function assertProcessGroupTargetLaunch(value, dir, operationId, launchId
|
|
|
343
380
|
!z.string().uuid().safeParse(r.lastLaunch?.requestId).success ||
|
|
344
381
|
!digest.safeParse(r.configurationChecksum).success)
|
|
345
382
|
throw Error();
|
|
383
|
+
if ("configurationGroupSha256" in value && value.configurationGroupSha256 !== undefined &&
|
|
384
|
+
(r.configurationGroupSha256 !== value.configurationGroupSha256 || r.generationId !== value.generationId))
|
|
385
|
+
throw Error();
|
|
346
386
|
}
|
|
347
387
|
catch {
|
|
348
388
|
throw Error("Target requires its exact reviewed group reservation and launch identity");
|