prae-cli 0.10.0 → 0.10.2

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.
@@ -1,448 +0,0 @@
1
- import { t as FRAMEWORKS } from "./frameworks-BgZHGKiH.js";
2
-
3
- //#region ../kernel/src/pack.ts
4
- function isObject(value) {
5
- return typeof value === "object" && value !== null && !Array.isArray(value);
6
- }
7
- var Check = class {
8
- errors = [];
9
- fail(path, message) {
10
- this.errors.push({
11
- path,
12
- message
13
- });
14
- }
15
- /** Reject any key the shape does not define. */
16
- keys(path, value, allowed) {
17
- for (const key of Object.keys(value)) if (!allowed.includes(key)) this.fail(`${path}.${key}`, `unknown field \`${key}\`; expected one of ${allowed.map((k) => `\`${k}\``).join(", ")}`);
18
- }
19
- text(path, value) {
20
- if (typeof value !== "string" || value.trim() === "") {
21
- this.fail(path, "expected a non-empty string");
22
- return;
23
- }
24
- return value;
25
- }
26
- /** A field that accepts one name or a list of them. */
27
- names(path, value) {
28
- if (typeof value === "string") return value;
29
- if (Array.isArray(value)) {
30
- const out = [];
31
- value.forEach((entry, index) => {
32
- const one = this.text(`${path}[${index}]`, entry);
33
- if (one !== void 0) out.push(one);
34
- });
35
- return out;
36
- }
37
- this.fail(path, "expected a string or an array of strings");
38
- }
39
- globs(path, value) {
40
- if (!Array.isArray(value)) {
41
- this.fail(path, "expected an array of path globs");
42
- return;
43
- }
44
- const out = [];
45
- value.forEach((entry, index) => {
46
- const one = this.text(`${path}[${index}]`, entry);
47
- if (one !== void 0) out.push(one);
48
- });
49
- return out;
50
- }
51
- number(path, value) {
52
- if (typeof value !== "number" || !Number.isFinite(value)) {
53
- this.fail(path, "expected a finite number");
54
- return;
55
- }
56
- return value;
57
- }
58
- };
59
- function readCommandMatch(check, path, value) {
60
- if (!isObject(value)) {
61
- check.fail(path, "expected an object");
62
- return;
63
- }
64
- check.keys(path, value, [
65
- "name",
66
- "token",
67
- "anyToken",
68
- "pipedTo",
69
- "pipeline"
70
- ]);
71
- if (value.name === void 0 && value.token === void 0 && value.anyToken === void 0 && value.pipedTo === void 0 && value.pipeline === void 0) check.fail(path, "expected `name`, `token`, `anyToken`, `pipedTo` or `pipeline`; a command matcher with none matches nothing");
72
- const out = {};
73
- if (value.token !== void 0) {
74
- const tokens = check.names(`${path}.token`, value.token);
75
- if (tokens !== void 0) out.token = tokens;
76
- }
77
- if (value.name !== void 0) {
78
- const names = check.names(`${path}.name`, value.name);
79
- if (names !== void 0) out.name = names;
80
- }
81
- if (value.anyToken !== void 0) {
82
- const tokens = check.names(`${path}.anyToken`, value.anyToken);
83
- if (tokens !== void 0) out.anyToken = tokens;
84
- }
85
- if (value.pipedTo !== void 0) {
86
- const pipes = check.names(`${path}.pipedTo`, value.pipedTo);
87
- if (pipes !== void 0) out.pipedTo = pipes;
88
- }
89
- if (value.pipeline !== void 0) {
90
- const shapes = check.names(`${path}.pipeline`, value.pipeline);
91
- if (shapes !== void 0) out.pipeline = shapes;
92
- }
93
- return out;
94
- }
95
- function readPathMatch(check, path, value) {
96
- if (!isObject(value)) {
97
- check.fail(path, "expected an object");
98
- return;
99
- }
100
- check.keys(path, value, [
101
- "arg",
102
- "outside",
103
- "inside"
104
- ]);
105
- if (value.outside === void 0 && value.inside === void 0) check.fail(path, "expected `inside` or `outside`; a path matcher with neither matches nothing");
106
- const out = {};
107
- if (value.arg !== void 0) {
108
- const arg = check.text(`${path}.arg`, value.arg);
109
- if (arg !== void 0) out.arg = arg;
110
- }
111
- if (value.outside !== void 0) {
112
- const globs = check.globs(`${path}.outside`, value.outside);
113
- if (globs !== void 0) out.outside = globs;
114
- }
115
- if (value.inside !== void 0) {
116
- const globs = check.globs(`${path}.inside`, value.inside);
117
- if (globs !== void 0) out.inside = globs;
118
- }
119
- return out;
120
- }
121
- function readHostMatch(check, path, value) {
122
- if (!isObject(value)) {
123
- check.fail(path, "expected an object");
124
- return;
125
- }
126
- check.keys(path, value, [
127
- "arg",
128
- "in",
129
- "notIn"
130
- ]);
131
- if (value.in === void 0 && value.notIn === void 0) check.fail(path, "expected `in` or `notIn`; a host matcher with neither matches nothing");
132
- const out = {};
133
- if (value.arg !== void 0) {
134
- const arg = check.text(`${path}.arg`, value.arg);
135
- if (arg !== void 0) out.arg = arg;
136
- }
137
- if (value.in !== void 0) {
138
- const list = check.globs(`${path}.in`, value.in);
139
- if (list !== void 0) out.in = list;
140
- }
141
- if (value.notIn !== void 0) {
142
- const list = check.globs(`${path}.notIn`, value.notIn);
143
- if (list !== void 0) out.notIn = list;
144
- }
145
- return out;
146
- }
147
- function readArgMatch(check, path, value) {
148
- if (!isObject(value)) {
149
- check.fail(path, "expected an object");
150
- return;
151
- }
152
- check.keys(path, value, [
153
- "name",
154
- "above",
155
- "below",
156
- "equals",
157
- "oneOf",
158
- "present"
159
- ]);
160
- const name = check.text(`${path}.name`, value.name);
161
- if (name === void 0) return void 0;
162
- const out = { name };
163
- if (value.above !== void 0) {
164
- const n = check.number(`${path}.above`, value.above);
165
- if (n !== void 0) out.above = n;
166
- }
167
- if (value.below !== void 0) {
168
- const n = check.number(`${path}.below`, value.below);
169
- if (n !== void 0) out.below = n;
170
- }
171
- if (value.equals !== void 0) out.equals = value.equals;
172
- if (value.oneOf !== void 0) if (!Array.isArray(value.oneOf)) check.fail(`${path}.oneOf`, "expected an array");
173
- else out.oneOf = value.oneOf;
174
- if (value.present !== void 0) if (typeof value.present !== "boolean") check.fail(`${path}.present`, "expected a boolean");
175
- else out.present = value.present;
176
- return out;
177
- }
178
- function readSecretsMatch(check, path, value) {
179
- if (!isObject(value)) {
180
- check.fail(path, "expected an object");
181
- return;
182
- }
183
- check.keys(path, value, [
184
- "types",
185
- "minConfidence",
186
- "atLeast"
187
- ]);
188
- const out = {};
189
- if (value.types !== void 0) {
190
- const types = check.globs(`${path}.types`, value.types);
191
- if (types !== void 0) out.types = types;
192
- }
193
- if (value.minConfidence !== void 0) {
194
- const n = check.number(`${path}.minConfidence`, value.minConfidence);
195
- if (n !== void 0) if (n < 0 || n > 1) check.fail(`${path}.minConfidence`, "expected a number between 0 and 1");
196
- else out.minConfidence = n;
197
- }
198
- if (value.atLeast !== void 0) {
199
- const n = check.number(`${path}.atLeast`, value.atLeast);
200
- if (n !== void 0) if (!Number.isInteger(n) || n < 1) check.fail(`${path}.atLeast`, "expected an integer of at least 1");
201
- else out.atLeast = n;
202
- }
203
- return out;
204
- }
205
- function readMatch(check, path, value) {
206
- if (!isObject(value)) {
207
- check.fail(path, "expected an object");
208
- return {};
209
- }
210
- check.keys(path, value, [
211
- "tool",
212
- "capability",
213
- "plugin",
214
- "agent",
215
- "command",
216
- "path",
217
- "host",
218
- "arg",
219
- "count",
220
- "secrets"
221
- ]);
222
- const out = {};
223
- for (const key of [
224
- "tool",
225
- "capability",
226
- "plugin",
227
- "agent"
228
- ]) if (value[key] !== void 0) {
229
- const names = check.names(`${path}.${key}`, value[key]);
230
- if (names !== void 0) out[key] = names;
231
- }
232
- if (value.command !== void 0) {
233
- const match = readCommandMatch(check, `${path}.command`, value.command);
234
- if (match !== void 0) out.command = match;
235
- }
236
- if (value.path !== void 0) {
237
- const match = readPathMatch(check, `${path}.path`, value.path);
238
- if (match !== void 0) out.path = match;
239
- }
240
- if (value.host !== void 0) {
241
- const match = readHostMatch(check, `${path}.host`, value.host);
242
- if (match !== void 0) out.host = match;
243
- }
244
- if (value.arg !== void 0) if (!Array.isArray(value.arg)) check.fail(`${path}.arg`, "expected an array of argument matchers");
245
- else {
246
- const list = [];
247
- value.arg.forEach((entry, index) => {
248
- const one = readArgMatch(check, `${path}.arg[${index}]`, entry);
249
- if (one !== void 0) list.push(one);
250
- });
251
- out.arg = list;
252
- }
253
- if (value.count !== void 0) if (!isObject(value.count)) check.fail(`${path}.count`, "expected an object");
254
- else {
255
- check.keys(`${path}.count`, value.count, ["above"]);
256
- const above = check.number(`${path}.count.above`, value.count.above);
257
- if (above !== void 0) out.count = { above };
258
- }
259
- if (value.secrets !== void 0) {
260
- const match = readSecretsMatch(check, `${path}.secrets`, value.secrets);
261
- if (match !== void 0) out.secrets = match;
262
- }
263
- return out;
264
- }
265
- function readEffect(check, path, value) {
266
- if (!isObject(value)) {
267
- check.fail(path, "expected an object");
268
- return;
269
- }
270
- const kind = value.kind === "hold" ? "ask" : value.kind;
271
- if (kind !== "deny" && kind !== "ask" && kind !== "correct" && kind !== "warn" && kind !== "allow") {
272
- check.fail(`${path}.kind`, "expected `allow`, `deny`, `hold` (or `ask`), `correct`, or `warn`");
273
- return;
274
- }
275
- check.keys(path, value, kind === "correct" ? [
276
- "kind",
277
- "set",
278
- "because"
279
- ] : ["kind", "because"]);
280
- const because = check.text(`${path}.because`, value.because);
281
- if (because === void 0) return void 0;
282
- if (kind === "correct") {
283
- if (!isObject(value.set) || Object.keys(value.set).length === 0) {
284
- check.fail(`${path}.set`, "expected a non-empty object of arguments to set");
285
- return;
286
- }
287
- return {
288
- kind,
289
- set: value.set,
290
- because
291
- };
292
- }
293
- return {
294
- kind,
295
- because
296
- };
297
- }
298
- function readRule(check, path, value) {
299
- if (!isObject(value)) {
300
- check.fail(path, "expected an object");
301
- return;
302
- }
303
- check.keys(path, value, [
304
- "id",
305
- "title",
306
- "description",
307
- "when",
308
- "effect",
309
- "frameworks"
310
- ]);
311
- const id = check.text(`${path}.id`, value.id);
312
- const effect = readEffect(check, `${path}.effect`, value.effect);
313
- if (value.when === void 0) check.fail(`${path}.when`, "expected an object");
314
- const when = readMatch(check, `${path}.when`, value.when ?? {});
315
- if (id === void 0 || effect === void 0) return void 0;
316
- const rule = {
317
- id,
318
- when,
319
- effect
320
- };
321
- if (value.title !== void 0) {
322
- const title = check.text(`${path}.title`, value.title);
323
- if (title !== void 0) rule.title = title;
324
- }
325
- if (value.description !== void 0) {
326
- const description = check.text(`${path}.description`, value.description);
327
- if (description !== void 0) rule.description = description;
328
- }
329
- if (value.frameworks !== void 0) {
330
- const frameworks = readFrameworks(check, `${path}.frameworks`, value.frameworks);
331
- if (frameworks !== void 0) rule.frameworks = frameworks;
332
- }
333
- return rule;
334
- }
335
- /**
336
- * A citation names a framework edition and controls the registry knows. A
337
- * typo here would be a rule that claims a mapping no view can render, so it
338
- * is a pack error rather than an ignored key — the same line the rest of the
339
- * parser takes.
340
- */
341
- function readFrameworks(check, path, value) {
342
- if (!isObject(value)) {
343
- check.fail(path, "expected an object keyed by framework id");
344
- return;
345
- }
346
- const out = {};
347
- for (const [framework, controls] of Object.entries(value)) {
348
- const known = FRAMEWORKS[framework];
349
- if (known === void 0) {
350
- check.fail(`${path}.${framework}`, `unknown framework; expected one of ${Object.keys(FRAMEWORKS).map((k) => `\`${k}\``).join(", ")}`);
351
- continue;
352
- }
353
- if (!Array.isArray(controls) || !controls.every((c) => typeof c === "string")) {
354
- check.fail(`${path}.${framework}`, "expected an array of control ids");
355
- continue;
356
- }
357
- const ids = controls;
358
- for (const control of ids) if (known.controls[control] === void 0) check.fail(`${path}.${framework}`, `unknown control \`${control}\` in ${known.name}`);
359
- if (ids.length > 0) out[framework] = [...new Set(ids)];
360
- }
361
- return out;
362
- }
363
- /** Parse and validate a pack. Never throws; every problem lands in `errors`. */
364
- function parsePack(source) {
365
- let raw;
366
- try {
367
- raw = JSON.parse(source);
368
- } catch (error) {
369
- return {
370
- ok: false,
371
- errors: [{
372
- path: "",
373
- message: `invalid JSON: ${error instanceof Error ? error.message : String(error)}`
374
- }]
375
- };
376
- }
377
- const check = new Check();
378
- if (!isObject(raw)) return {
379
- ok: false,
380
- errors: [{
381
- path: "",
382
- message: "expected an object"
383
- }]
384
- };
385
- check.keys("", raw, [
386
- "prae",
387
- "pack",
388
- "version",
389
- "description",
390
- "owner",
391
- "expires_at",
392
- "baseline",
393
- "rules"
394
- ]);
395
- if (raw.prae !== "0.1") check.fail(".prae", "expected `\"0.1\"`; this is the only pack version this build reads");
396
- const name = check.text(".pack", raw.pack);
397
- const version = check.text(".version", raw.version);
398
- const description = raw.description === void 0 ? void 0 : check.text(".description", raw.description);
399
- const owner = raw.owner === void 0 ? void 0 : check.text(".owner", raw.owner);
400
- const expires = raw.expires_at === void 0 ? void 0 : check.text(".expires_at", raw.expires_at);
401
- if (expires !== void 0 && (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})$/.test(expires) || !Number.isFinite(Date.parse(expires)))) check.fail(".expires_at", "expected an ISO 8601 time with a zone, e.g. 2026-10-05T12:00:00Z");
402
- let baseline;
403
- if (raw.baseline !== void 0) if (!isObject(raw.baseline)) check.fail(".baseline", "expected an object");
404
- else {
405
- check.keys(".baseline", raw.baseline, ["capabilities"]);
406
- const caps = check.globs(".baseline.capabilities", raw.baseline.capabilities);
407
- if (caps !== void 0) baseline = { capabilities: caps };
408
- }
409
- const rules = [];
410
- if (!Array.isArray(raw.rules)) check.fail(".rules", "expected an array");
411
- else {
412
- const seen = /* @__PURE__ */ new Set();
413
- raw.rules.forEach((entry, index) => {
414
- const rule = readRule(check, `rules[${index}]`, entry);
415
- if (rule === void 0) return;
416
- if (seen.has(rule.id)) {
417
- check.fail(`rules[${index}].id`, `duplicate rule id \`${rule.id}\``);
418
- return;
419
- }
420
- seen.add(rule.id);
421
- rules.push(rule);
422
- });
423
- }
424
- if (check.errors.length > 0) return {
425
- ok: false,
426
- errors: check.errors
427
- };
428
- if (name === void 0 || version === void 0) return {
429
- ok: false,
430
- errors: check.errors
431
- };
432
- return {
433
- ok: true,
434
- pack: {
435
- prae: "0.1",
436
- pack: name,
437
- version,
438
- ...description === void 0 ? {} : { description },
439
- ...owner === void 0 ? {} : { owner },
440
- ...expires === void 0 ? {} : { expires_at: expires },
441
- ...baseline === void 0 ? {} : { baseline },
442
- rules
443
- }
444
- };
445
- }
446
-
447
- //#endregion
448
- export { parsePack as t };
File without changes
File without changes
File without changes
File without changes
File without changes