@parmanasystems/governance 1.71.26 → 1.71.38

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/dist/index.d.ts CHANGED
@@ -1,11 +1,30 @@
1
1
  import { DecisionResult } from '@parmanasystems/contracts';
2
2
 
3
+ interface PolicyCompileError {
4
+ code: string;
5
+ message: string;
6
+ field?: string;
7
+ }
8
+ interface PolicyCompileWarning {
9
+ code: string;
10
+ message: string;
11
+ }
12
+ interface PolicyCompileResult {
13
+ valid: boolean;
14
+ policyId: string;
15
+ policyVersion: string;
16
+ path: string;
17
+ errors: PolicyCompileError[];
18
+ warnings: PolicyCompileWarning[];
19
+ }
20
+ declare function compilePolicy(policyDirectory: string): PolicyCompileResult;
21
+
3
22
  /**
4
- * Scaffolds a new policy directory at `./policies/<policyId>/v1/` and writes
23
+ * Scaffolds a new policy directory at `./policies/<policyId>/1.0.0/` and writes
5
24
  * a skeleton `policy.json` to it.
6
25
  *
7
26
  * @param policyId - Unique policy identifier. Must not already exist on disk.
8
- * @returns Absolute path of the created `v1` version directory.
27
+ * @returns Absolute path of the created `1.0.0` version directory.
9
28
  * @throws When `./policies/<policyId>` already exists.
10
29
  */
11
30
  declare function createPolicy(policyId: string): string;
@@ -74,9 +93,9 @@ declare function generateBundle(policyId: string, policyVersion: string, policyD
74
93
 
75
94
  /**
76
95
  * Creates the next version directory for `policyId` by copying the latest
77
- * existing version and incrementing its numeric suffix (e.g. `v1` → `v2`).
78
- * The copied `policy.json` has its `version` field updated to the new version
79
- * string.
96
+ * existing version and incrementing it. Supports both semver (1.0.0) and
97
+ * legacy v-prefix (v1) directory formats. The copied `policy.json` has its
98
+ * version field updated to the new version string.
80
99
  *
81
100
  * @param policyId - An existing policy identifier under `./policies/`.
82
101
  * @returns Absolute path of the newly created version directory.
@@ -180,4 +199,4 @@ interface SchemaRuntime {
180
199
  }
181
200
  declare function loadSchemaRuntime(schemaVersion: string): SchemaRuntime;
182
201
 
183
- export { type BundleGenerationResult, type BundleSigner, type PolicyDefinition, type PolicyRule$1 as PolicyRule, type RuntimeRequirements, type SchemaRuntime, type SchemaV1Policy, createPolicy, definePolicy, evaluateSchemaV1, generateBundle, loadSchemaRuntime, schemaV1Operators, schemaV1Semantics, upgradePolicy, validatePolicy };
202
+ export { type BundleGenerationResult, type BundleSigner, type PolicyCompileError, type PolicyCompileResult, type PolicyCompileWarning, type PolicyDefinition, type PolicyRule$1 as PolicyRule, type RuntimeRequirements, type SchemaRuntime, type SchemaV1Policy, compilePolicy, createPolicy, definePolicy, evaluateSchemaV1, generateBundle, loadSchemaRuntime, schemaV1Operators, schemaV1Semantics, upgradePolicy, validatePolicy };
package/dist/index.js CHANGED
@@ -1,35 +1,231 @@
1
- // src/create-policy.ts
1
+ // src/compile-policy.ts
2
2
  import * as fs from "fs";
3
3
  import * as path from "path";
4
+ var SUPPORTED_SCHEMA_VERSIONS = ["1.0.0"];
5
+ var VALID_SIGNAL_TYPES = [
6
+ "integer",
7
+ "number",
8
+ "boolean",
9
+ "string",
10
+ "enum"
11
+ ];
12
+ var VALID_ACTIONS = [
13
+ "approve",
14
+ "reject",
15
+ "escalate",
16
+ "manual_review",
17
+ "document_required",
18
+ "auto_approve",
19
+ "fraud_review",
20
+ "pending_override"
21
+ ];
22
+ function extractSignalRefs(condition) {
23
+ if (!condition || typeof condition !== "object" || Array.isArray(condition)) {
24
+ return [];
25
+ }
26
+ const c = condition;
27
+ if (typeof c.signal === "string") return [c.signal];
28
+ if (Array.isArray(c.all)) return c.all.flatMap(extractSignalRefs);
29
+ if (Array.isArray(c.any)) return c.any.flatMap(extractSignalRefs);
30
+ return [];
31
+ }
32
+ function isCatchAll(condition) {
33
+ if (!condition || typeof condition !== "object" || Array.isArray(condition)) {
34
+ return false;
35
+ }
36
+ const c = condition;
37
+ return "all" in c && Array.isArray(c.all) && c.all.length === 0;
38
+ }
39
+ function compilePolicy(policyDirectory) {
40
+ const errors = [];
41
+ const warnings = [];
42
+ let policyId = "";
43
+ let policyVersion = "";
44
+ const err = (code, message, field) => errors.push({ code, message, ...field ? { field } : {} });
45
+ const warn = (code, message) => warnings.push({ code, message });
46
+ const policyFile = path.join(policyDirectory, "policy.json");
47
+ if (!fs.existsSync(policyFile)) {
48
+ err("POL-001", `policy.json not found at ${policyFile}`);
49
+ return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };
50
+ }
51
+ let content;
52
+ try {
53
+ const raw = fs.readFileSync(policyFile, "utf8");
54
+ const parsed = JSON.parse(raw);
55
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
56
+ err("POL-002", "Invalid JSON: expected object at top level");
57
+ return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };
58
+ }
59
+ content = parsed;
60
+ } catch (e) {
61
+ const msg = e instanceof Error ? e.message : String(e);
62
+ err("POL-002", `Invalid JSON: ${msg}`);
63
+ return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };
64
+ }
65
+ if (!content.policyId || typeof content.policyId !== "string") {
66
+ err("POL-003", "Missing required field: policyId", "policyId");
67
+ } else {
68
+ policyId = content.policyId;
69
+ }
70
+ if (!content.policyVersion || typeof content.policyVersion !== "string") {
71
+ err("POL-004", "Missing required field: policyVersion", "policyVersion");
72
+ } else {
73
+ policyVersion = content.policyVersion;
74
+ }
75
+ if (!content.schemaVersion || typeof content.schemaVersion !== "string") {
76
+ err("POL-005", "Missing required field: schemaVersion", "schemaVersion");
77
+ }
78
+ if (content.signalsSchema === null || content.signalsSchema === void 0 || typeof content.signalsSchema !== "object" || Array.isArray(content.signalsSchema)) {
79
+ err("POL-006", "Missing required field: signalsSchema", "signalsSchema");
80
+ }
81
+ if (!Array.isArray(content.rules)) {
82
+ err("POL-007", "Missing required field: rules", "rules");
83
+ }
84
+ if (policyId) {
85
+ const dirPolicyId = path.basename(path.dirname(policyDirectory));
86
+ if (dirPolicyId !== policyId) {
87
+ warn(
88
+ "POL-008",
89
+ `policyId in policy.json does not match directory name (directory: '${dirPolicyId}', policyId: '${policyId}')`
90
+ );
91
+ }
92
+ }
93
+ if (content.schemaVersion && typeof content.schemaVersion === "string") {
94
+ if (!SUPPORTED_SCHEMA_VERSIONS.includes(content.schemaVersion)) {
95
+ err(
96
+ "POL-009",
97
+ `Unsupported schemaVersion: ${content.schemaVersion}. Supported: ${SUPPORTED_SCHEMA_VERSIONS.join(", ")}`,
98
+ "schemaVersion"
99
+ );
100
+ }
101
+ }
102
+ const signalsSchema = content.signalsSchema;
103
+ const knownSignals = /* @__PURE__ */ new Set();
104
+ if (signalsSchema && typeof signalsSchema === "object" && !Array.isArray(signalsSchema)) {
105
+ for (const [name, def] of Object.entries(signalsSchema)) {
106
+ knownSignals.add(name);
107
+ if (!def || typeof def !== "object" || Array.isArray(def)) {
108
+ err("POL-010", `Signal '${name}' missing required 'type' field`, name);
109
+ continue;
110
+ }
111
+ const d = def;
112
+ if (!d.type || typeof d.type !== "string") {
113
+ err("POL-010", `Signal '${name}' missing required 'type' field`, name);
114
+ continue;
115
+ }
116
+ if (!VALID_SIGNAL_TYPES.includes(d.type)) {
117
+ err(
118
+ "POL-011",
119
+ `Signal '${name}' has invalid type '${d.type}'. Valid: ${VALID_SIGNAL_TYPES.join(", ")}`,
120
+ name
121
+ );
122
+ }
123
+ if (d.type === "enum") {
124
+ if (!Array.isArray(d.values) || d.values.length === 0) {
125
+ err("POL-012", `Signal '${name}' type 'enum' requires non-empty 'values' array`, name);
126
+ }
127
+ }
128
+ }
129
+ }
130
+ const rules = content.rules;
131
+ if (Array.isArray(rules)) {
132
+ const seenIds = /* @__PURE__ */ new Set();
133
+ for (let i = 0; i < rules.length; i++) {
134
+ const rule = rules[i];
135
+ if (!rule || typeof rule !== "object") {
136
+ err("POL-013", `Rule at index ${i} missing required 'id' field`);
137
+ continue;
138
+ }
139
+ const ruleId = typeof rule.id === "string" && rule.id.length > 0 ? rule.id : null;
140
+ if (!ruleId) {
141
+ err("POL-013", `Rule at index ${i} missing required 'id' field`);
142
+ continue;
143
+ }
144
+ if (seenIds.has(ruleId)) {
145
+ err("POL-020", `Duplicate rule id: '${ruleId}'`);
146
+ } else {
147
+ seenIds.add(ruleId);
148
+ }
149
+ if (!rule.condition || typeof rule.condition !== "object" || Array.isArray(rule.condition)) {
150
+ err("POL-014", `Rule '${ruleId}' missing required 'condition' field`);
151
+ } else {
152
+ for (const ref of extractSignalRefs(rule.condition)) {
153
+ if (knownSignals.size > 0 && !knownSignals.has(ref)) {
154
+ warn("POL-019", `Rule '${ruleId}' references signal '${ref}' not in signalsSchema`);
155
+ }
156
+ }
157
+ }
158
+ if (!rule.outcome || typeof rule.outcome !== "object" || Array.isArray(rule.outcome)) {
159
+ err("POL-015", `Rule '${ruleId}' missing required 'outcome' field`);
160
+ } else {
161
+ const outcome = rule.outcome;
162
+ if (!outcome.action || !VALID_ACTIONS.includes(outcome.action)) {
163
+ err(
164
+ "POL-016",
165
+ `Rule '${ruleId}' outcome.action '${outcome.action}' is not a valid action`
166
+ );
167
+ }
168
+ if (typeof outcome.requires_override !== "boolean") {
169
+ err("POL-017", `Rule '${ruleId}' outcome.requires_override must be boolean`);
170
+ }
171
+ if (outcome.reason !== void 0 && typeof outcome.reason !== "string") {
172
+ err("POL-018", `Rule '${ruleId}' outcome.reason must be string`);
173
+ }
174
+ }
175
+ }
176
+ const hasCatchAll = rules.some((r) => isCatchAll(r.condition));
177
+ if (!hasCatchAll) {
178
+ warn(
179
+ "POL-021",
180
+ "No catch-all rule found. Executions with unmatched signals will use default reject."
181
+ );
182
+ }
183
+ }
184
+ return {
185
+ valid: errors.length === 0,
186
+ policyId,
187
+ policyVersion,
188
+ path: policyDirectory,
189
+ errors,
190
+ warnings
191
+ };
192
+ }
193
+
194
+ // src/create-policy.ts
195
+ import * as fs2 from "fs";
196
+ import * as path2 from "path";
4
197
  function createPolicy(policyId) {
5
- const policyRoot = path.join(
198
+ const policyRoot = path2.join(
6
199
  "./policies",
7
200
  policyId
8
201
  );
9
- const versionDirectory = path.join(
202
+ const versionDirectory = path2.join(
10
203
  policyRoot,
11
- "v1"
204
+ "1.0.0"
12
205
  );
13
- if (fs.existsSync(policyRoot)) {
206
+ if (fs2.existsSync(policyRoot)) {
14
207
  throw new Error(
15
208
  `Policy already exists: ${policyId}`
16
209
  );
17
210
  }
18
- fs.mkdirSync(
211
+ fs2.mkdirSync(
19
212
  versionDirectory,
20
213
  {
21
214
  recursive: true
22
215
  }
23
216
  );
24
- fs.writeFileSync(
25
- path.join(
217
+ fs2.writeFileSync(
218
+ path2.join(
26
219
  versionDirectory,
27
220
  "policy.json"
28
221
  ),
29
222
  JSON.stringify(
30
223
  {
31
- policy: policyId,
32
- version: "v1"
224
+ policyId,
225
+ policyVersion: "1.0.0",
226
+ schemaVersion: "1.0.0",
227
+ signalsSchema: {},
228
+ rules: []
33
229
  },
34
230
  null,
35
231
  2
@@ -40,7 +236,7 @@ function createPolicy(policyId) {
40
236
  }
41
237
 
42
238
  // src/generate-bundle.ts
43
- import * as path2 from "path";
239
+ import * as path3 from "path";
44
240
  import {
45
241
  generateManifest,
46
242
  writeManifest
@@ -50,9 +246,20 @@ import {
50
246
  writeSignature
51
247
  } from "@parmanasystems/crypto";
52
248
  function generateBundle(policyId, policyVersion, policyDirectory, signer) {
53
- const directory = path2.resolve(
249
+ const directory = path3.resolve(
54
250
  policyDirectory
55
251
  );
252
+ const compileResult = compilePolicy(directory);
253
+ if (compileResult.errors.length > 0) {
254
+ const messages = compileResult.errors.map((e) => ` ${e.code}: ${e.message}`).join("\n");
255
+ throw new Error(
256
+ `Policy validation failed \u2014 cannot generate bundle:
257
+ ${messages}`
258
+ );
259
+ }
260
+ for (const w of compileResult.warnings) {
261
+ console.warn(`[policy-compiler] ${w.code}: ${w.message}`);
262
+ }
56
263
  const manifest = generateManifest(
57
264
  policyId,
58
265
  policyVersion,
@@ -62,7 +269,7 @@ function generateBundle(policyId, policyVersion, policyDirectory, signer) {
62
269
  manifest,
63
270
  directory
64
271
  );
65
- const manifestPath = path2.join(
272
+ const manifestPath = path3.join(
66
273
  directory,
67
274
  "bundle.manifest.json"
68
275
  );
@@ -79,73 +286,71 @@ function generateBundle(policyId, policyVersion, policyDirectory, signer) {
79
286
  return {
80
287
  success: true,
81
288
  manifest_path: manifestPath,
82
- signature_path: signer ? path2.join(directory, "bundle.sig") : null,
289
+ signature_path: signer ? path3.join(directory, "bundle.sig") : null,
83
290
  bundle_hash: manifest.bundle_hash
84
291
  };
85
292
  }
86
293
 
87
294
  // src/upgrade-policy.ts
88
- import * as fs2 from "fs";
89
- import * as path3 from "path";
295
+ import * as fs3 from "fs";
296
+ import * as path4 from "path";
90
297
  function upgradePolicy(policyId) {
91
- const policyRoot = path3.join(
298
+ const policyRoot = path4.join(
92
299
  "./policies",
93
300
  policyId
94
301
  );
95
- if (!fs2.existsSync(policyRoot)) {
302
+ if (!fs3.existsSync(policyRoot)) {
96
303
  throw new Error(
97
304
  `Policy does not exist: ${policyId}`
98
305
  );
99
306
  }
100
- const versions = fs2.readdirSync(policyRoot).filter(
101
- (entry) => entry.startsWith("v")
102
- ).sort();
103
- const latestVersion = versions[versions.length - 1];
104
- const latestNumber = Number(
105
- latestVersion.replace("v", "")
106
- );
107
- const nextVersion = `v${latestNumber + 1}`;
108
- const latestDirectory = path3.join(
109
- policyRoot,
110
- latestVersion
111
- );
112
- const nextDirectory = path3.join(
113
- policyRoot,
114
- nextVersion
115
- );
116
- fs2.cpSync(
117
- latestDirectory,
118
- nextDirectory,
119
- {
120
- recursive: true
121
- }
122
- );
123
- const policyFile = path3.join(
124
- nextDirectory,
125
- "policy.json"
307
+ const allDirs = fs3.readdirSync(policyRoot);
308
+ const versions = allDirs.filter(
309
+ (e) => /^\d+\.\d+\.\d+$/.test(e) || /^v\d+$/.test(e)
126
310
  );
311
+ if (versions.length === 0) {
312
+ throw new Error(
313
+ `No version directories found for policy: ${policyId}`
314
+ );
315
+ }
316
+ const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
317
+ versions.sort((a, b) => {
318
+ const [aMaj, aMin = 0, aPatch = 0] = parse(a);
319
+ const [bMaj, bMin = 0, bPatch = 0] = parse(b);
320
+ return aMaj !== bMaj ? aMaj - bMaj : aMin !== bMin ? aMin - bMin : aPatch - bPatch;
321
+ });
322
+ const latestVersion = versions[versions.length - 1];
323
+ let nextVersion;
324
+ if (/^\d+\.\d+\.\d+$/.test(latestVersion)) {
325
+ const [maj, min, patch] = latestVersion.split(".").map(Number);
326
+ nextVersion = `${maj}.${min}.${patch + 1}`;
327
+ } else {
328
+ const latestNumber = Number(latestVersion.replace("v", ""));
329
+ nextVersion = `v${latestNumber + 1}`;
330
+ }
331
+ const latestDirectory = path4.join(policyRoot, latestVersion);
332
+ const nextDirectory = path4.join(policyRoot, nextVersion);
333
+ fs3.cpSync(latestDirectory, nextDirectory, { recursive: true });
334
+ const policyFile = path4.join(nextDirectory, "policy.json");
127
335
  const content = JSON.parse(
128
- fs2.readFileSync(
129
- policyFile,
130
- "utf8"
131
- )
336
+ fs3.readFileSync(policyFile, "utf8")
132
337
  );
133
- content.version = nextVersion;
134
- fs2.writeFileSync(
338
+ if ("policyVersion" in content) {
339
+ content.policyVersion = nextVersion;
340
+ } else {
341
+ content.version = nextVersion;
342
+ }
343
+ fs3.writeFileSync(
135
344
  policyFile,
136
- JSON.stringify(
137
- content,
138
- null,
139
- 2
140
- ),
345
+ JSON.stringify(content, null, 2),
141
346
  "utf8"
142
347
  );
143
348
  return nextDirectory;
144
349
  }
145
350
 
146
351
  // src/validate-policy.ts
147
- import * as fs3 from "fs";
148
- import * as path4 from "path";
352
+ import * as fs4 from "fs";
353
+ import * as path5 from "path";
149
354
  import {
150
355
  readManifest,
151
356
  verifyManifest
@@ -155,32 +360,32 @@ import {
155
360
  verifySignature
156
361
  } from "@parmanasystems/crypto";
157
362
  function validatePolicy(policyId, publicKeyPath) {
158
- const policyRoot = path4.join(
363
+ const policyRoot = path5.join(
159
364
  "./policies",
160
365
  policyId
161
366
  );
162
- if (!fs3.existsSync(
367
+ if (!fs4.existsSync(
163
368
  policyRoot
164
369
  )) {
165
370
  throw new Error(
166
371
  `Policy does not exist: ${policyId}`
167
372
  );
168
373
  }
169
- const versions = fs3.readdirSync(
374
+ const versions = fs4.readdirSync(
170
375
  policyRoot
171
376
  ).filter(
172
377
  (entry) => entry.startsWith("v")
173
378
  ).sort();
174
379
  for (const version of versions) {
175
- const versionDirectory = path4.join(
380
+ const versionDirectory = path5.join(
176
381
  policyRoot,
177
382
  version
178
383
  );
179
- const manifestPath = path4.join(
384
+ const manifestPath = path5.join(
180
385
  versionDirectory,
181
386
  "bundle.manifest.json"
182
387
  );
183
- if (!fs3.existsSync(
388
+ if (!fs4.existsSync(
184
389
  manifestPath
185
390
  )) {
186
391
  continue;
@@ -195,11 +400,11 @@ function validatePolicy(policyId, publicKeyPath) {
195
400
  if (!manifestResult.valid) {
196
401
  return false;
197
402
  }
198
- const sigPath = path4.join(
403
+ const sigPath = path5.join(
199
404
  versionDirectory,
200
405
  "bundle.sig"
201
406
  );
202
- if (!publicKeyPath || !fs3.existsSync(sigPath)) {
407
+ if (!publicKeyPath || !fs4.existsSync(sigPath)) {
203
408
  continue;
204
409
  }
205
410
  const signature = readSignature(
@@ -317,30 +522,37 @@ function evaluateSchemaV1(policy, signals) {
317
522
  };
318
523
  }
319
524
  }
320
- throw new Error(
321
- "[SYS-006] No rule matched \u2014 policy must cover all cases"
322
- );
525
+ return {
526
+ status: "decided",
527
+ outcome: {
528
+ action: "reject",
529
+ requires_override: false,
530
+ reason: "[SYS-006] No rule matched \u2014 default reject. Add a catch-all rule to make this explicit."
531
+ },
532
+ rule_id: "default",
533
+ source: "rule_match"
534
+ };
323
535
  }
324
536
 
325
537
  // src/schema/load-schema-runtime.ts
538
+ var SUPPORTED_SCHEMA_VERSIONS2 = {
539
+ "1.0.0": {
540
+ semantics: schemaV1Semantics,
541
+ operators: schemaV1Operators,
542
+ evaluate: evaluateSchemaV1
543
+ }
544
+ };
326
545
  function loadSchemaRuntime(schemaVersion) {
327
- const major = Number(
328
- schemaVersion.split(".")[0]
329
- );
330
- switch (major) {
331
- case 1:
332
- return {
333
- semantics: schemaV1Semantics,
334
- operators: schemaV1Operators,
335
- evaluate: evaluateSchemaV1
336
- };
337
- default:
338
- throw new Error(
339
- `Unsupported schema version: ${schemaVersion}`
340
- );
546
+ const runtime = SUPPORTED_SCHEMA_VERSIONS2[schemaVersion];
547
+ if (!runtime) {
548
+ throw new Error(
549
+ `Unsupported schema version: ${schemaVersion}. Supported: ${Object.keys(SUPPORTED_SCHEMA_VERSIONS2).join(", ")}`
550
+ );
341
551
  }
552
+ return runtime;
342
553
  }
343
554
  export {
555
+ compilePolicy,
344
556
  createPolicy,
345
557
  definePolicy,
346
558
  evaluateSchemaV1,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/create-policy.ts","../src/generate-bundle.ts","../src/upgrade-policy.ts","../src/validate-policy.ts","../src/define-policy.ts","../src/schema/v1/semantics.ts","../src/schema/v1/operators.ts","../src/schema/v1/evaluator.ts","../src/schema/load-schema-runtime.ts"],"sourcesContent":["import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Scaffolds a new policy directory at `./policies/<policyId>/v1/` and writes\r\n * a skeleton `policy.json` to it.\r\n *\r\n * @param policyId - Unique policy identifier. Must not already exist on disk.\r\n * @returns Absolute path of the created `v1` version directory.\r\n * @throws When `./policies/<policyId>` already exists.\r\n */\r\nexport function createPolicy(\r\n policyId: string\r\n): string {\r\n const policyRoot = path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n const versionDirectory =\r\n path.join(\r\n policyRoot,\r\n \"v1\"\r\n );\r\n\r\n if (fs.existsSync(policyRoot)) {\r\n throw new Error(\r\n `Policy already exists: ${policyId}`\r\n );\r\n }\r\n\r\n fs.mkdirSync(\r\n versionDirectory,\r\n {\r\n recursive: true,\r\n }\r\n );\r\n\r\n fs.writeFileSync(\r\n path.join(\r\n versionDirectory,\r\n \"policy.json\"\r\n ),\r\n\r\n JSON.stringify(\r\n {\r\n policy: policyId,\r\n version: \"v1\",\r\n },\r\n null,\r\n 2\r\n ),\r\n\r\n \"utf8\"\r\n );\r\n\r\n return versionDirectory;\r\n}\r\n\r\n\r\n\r\n\r\n","import * as path from \"node:path\";\r\n\r\nimport {\r\n generateManifest,\r\n writeManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n signManifest,\r\n writeSignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\nimport type {\r\n BundleGenerationResult,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Signer configuration for {@link generateBundle}.\r\n * Provide an explicit private key path — never rely on implicit trust key discovery.\r\n */\r\nexport interface BundleSigner {\r\n /** Absolute or CWD-relative path to the PEM-encoded Ed25519 private key. */\r\n privateKeyPath: string;\r\n}\r\n\r\n/**\r\n * Generates a content-addressed bundle for `policyId`/`policyVersion` in `policyDirectory`:\r\n * 1. Hashes all artifacts and writes `bundle.manifest.json`.\r\n * 2. If `signer` is provided: signs the manifest and writes `bundle.sig`.\r\n * If no signer: produces an unsigned bundle (`bundle.sig` is not written).\r\n *\r\n * Unsigned bundles are valid for development.\r\n * Production deployments should provide a signer.\r\n *\r\n * @param policyId - Policy identifier embedded in the manifest.\r\n * @param policyVersion - Policy version string (e.g. `\"v1\"`).\r\n * @param policyDirectory - Path to the directory containing the policy artifacts.\r\n * @param signer - Optional signing configuration. Omit to produce an unsigned bundle.\r\n * @returns Paths to the written files and the deterministic bundle hash.\r\n */\r\nexport function generateBundle(\r\n policyId: string,\r\n policyVersion: string,\r\n policyDirectory: string,\r\n signer?: BundleSigner\r\n): BundleGenerationResult {\r\n\r\n const directory =\r\n path.resolve(\r\n policyDirectory\r\n );\r\n\r\n const manifest =\r\n generateManifest(\r\n policyId,\r\n policyVersion,\r\n directory\r\n );\r\n\r\n writeManifest(\r\n manifest,\r\n directory\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n directory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (signer) {\r\n const signature =\r\n signManifest(\r\n manifestPath,\r\n signer.privateKeyPath\r\n );\r\n\r\n writeSignature(\r\n signature,\r\n directory\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n\r\n manifest_path:\r\n manifestPath,\r\n\r\n signature_path:\r\n signer\r\n ? path.join(directory, \"bundle.sig\")\r\n : null,\r\n\r\n bundle_hash:\r\n manifest.bundle_hash,\r\n };\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Creates the next version directory for `policyId` by copying the latest\r\n * existing version and incrementing its numeric suffix (e.g. `v1` → `v2`).\r\n * The copied `policy.json` has its `version` field updated to the new version\r\n * string.\r\n *\r\n * @param policyId - An existing policy identifier under `./policies/`.\r\n * @returns Absolute path of the newly created version directory.\r\n * @throws When the policy does not exist on disk.\r\n */\r\nexport function upgradePolicy(\r\n policyId: string\r\n): string {\r\n const policyRoot = path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n if (!fs.existsSync(policyRoot)) {\r\n throw new Error(\r\n `Policy does not exist: ${policyId}`\r\n );\r\n }\r\n\r\n const versions = fs\r\n .readdirSync(policyRoot)\r\n .filter((entry) =>\r\n entry.startsWith(\"v\")\r\n )\r\n .sort();\r\n\r\n const latestVersion =\r\n versions[\r\n versions.length - 1\r\n ];\r\n\r\n const latestNumber =\r\n Number(\r\n latestVersion.replace(\"v\", \"\")\r\n );\r\n\r\n const nextVersion =\r\n `v${latestNumber + 1}`;\r\n\r\n const latestDirectory =\r\n path.join(\r\n policyRoot,\r\n latestVersion\r\n );\r\n\r\n const nextDirectory =\r\n path.join(\r\n policyRoot,\r\n nextVersion\r\n );\r\n\r\n fs.cpSync(\r\n latestDirectory,\r\n nextDirectory,\r\n {\r\n recursive: true,\r\n }\r\n );\r\n\r\n const policyFile =\r\n path.join(\r\n nextDirectory,\r\n \"policy.json\"\r\n );\r\n\r\n const content =\r\n JSON.parse(\r\n fs.readFileSync(\r\n policyFile,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n content.version =\r\n nextVersion;\r\n\r\n fs.writeFileSync(\r\n policyFile,\r\n JSON.stringify(\r\n content,\r\n null,\r\n 2\r\n ),\r\n \"utf8\"\r\n );\r\n\r\n return nextDirectory;\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\nimport {\r\n readManifest,\r\n verifyManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n readSignature,\r\n verifySignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\n/**\r\n * Validates every version directory under `./policies/<policyId>` by\r\n * re-verifying all bundle manifests (content hashes) and, when a public key\r\n * path is provided, cryptographic signatures (bundle.sig).\r\n *\r\n * - Version directories without a `bundle.manifest.json` (not yet bundled) are skipped.\r\n * - Version directories without a `bundle.sig` skip signature verification.\r\n * - When `publicKeyPath` is omitted, signature verification is skipped for all versions.\r\n *\r\n * Returns `true` only when every bundled version passes all applicable checks.\r\n *\r\n * @param policyId - Policy identifier whose version directories will be checked.\r\n * @param publicKeyPath - Optional explicit path to the PEM-encoded public key for\r\n * signature verification. When omitted, only manifest content\r\n * hashes are verified.\r\n * @throws When the policy directory does not exist.\r\n */\r\nexport function validatePolicy(\r\n policyId: string,\r\n publicKeyPath?: string\r\n): boolean {\r\n\r\n const policyRoot =\r\n path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n policyRoot\r\n )\r\n ) {\r\n throw new Error(\r\n `Policy does not exist: ${policyId}`\r\n );\r\n }\r\n\r\n const versions =\r\n fs\r\n .readdirSync(\r\n policyRoot\r\n )\r\n .filter(\r\n (entry) =>\r\n entry.startsWith(\"v\")\r\n )\r\n .sort();\r\n\r\n for (const version of versions) {\r\n\r\n const versionDirectory =\r\n path.join(\r\n policyRoot,\r\n version\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n manifestPath\r\n )\r\n ) {\r\n continue;\r\n }\r\n\r\n const manifest =\r\n readManifest(\r\n versionDirectory\r\n );\r\n\r\n const manifestResult =\r\n verifyManifest(\r\n manifest,\r\n versionDirectory\r\n );\r\n\r\n if (\r\n !manifestResult.valid\r\n ) {\r\n return false;\r\n }\r\n\r\n const sigPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.sig\"\r\n );\r\n\r\n if (\r\n !publicKeyPath ||\r\n !fs.existsSync(sigPath)\r\n ) {\r\n continue;\r\n }\r\n\r\n const signature =\r\n readSignature(\r\n versionDirectory\r\n );\r\n\r\n const signatureValid =\r\n verifySignature(\r\n manifestPath,\r\n signature,\r\n publicKeyPath\r\n );\r\n\r\n if (\r\n !signatureValid\r\n ) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n\r\n\r\n\r\n","import type {\r\n PolicyDefinition,\r\n PolicyRule,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Constructs a {@link PolicyDefinition} from a plain config object.\r\n * Use this as the first step in the policy-authoring pipeline before\r\n * serializing the policy to disk and calling {@link generateBundle}.\r\n *\r\n * @param config - Policy id, version, and rules.\r\n */\r\nexport function definePolicy(config: {\r\n id: string;\r\n version: string;\r\n rules: PolicyRule[];\r\n}): PolicyDefinition {\r\n\r\n return {\r\n id: config.id,\r\n\r\n version: config.version,\r\n\r\n rules: config.rules,\r\n };\r\n}\r\n","export const schemaV1Semantics = {\r\n\r\n schemaVersion:\r\n \"1.0.0\",\r\n\r\n ruleConditionField:\r\n \"condition\",\r\n\r\n ruleOutcomeField:\r\n \"outcome\",\r\n\r\n signalReferenceField:\r\n \"signal\",\r\n\r\n supportedOperators: [\r\n \"equals\",\r\n \"greater_than\",\r\n \"less_than\",\r\n ],\r\n};\r\n","export const schemaV1Operators = {\r\n\r\n equals(\r\n left: unknown,\r\n right: unknown\r\n ): boolean {\r\n\r\n return left === right;\r\n },\r\n\r\n greater_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left > right;\r\n },\r\n\r\n less_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left < right;\r\n },\r\n};\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./operators.js\";\r\n\r\ninterface BaseCondition {\r\n signal: string;\r\n equals?: unknown;\r\n greater_than?: number;\r\n less_than?: number;\r\n}\r\n\r\ninterface AllCondition {\r\n all: RuleCondition[];\r\n}\r\n\r\ninterface AnyCondition {\r\n any: RuleCondition[];\r\n}\r\n\r\ntype RuleCondition =\r\n | BaseCondition\r\n | AllCondition\r\n | AnyCondition;\r\n\r\ninterface PolicyRule {\r\n id: string;\r\n\r\n condition: RuleCondition;\r\n\r\n outcome: {\r\n action:\r\n | \"approve\"\r\n | \"reject\";\r\n\r\n requires_override:\r\n boolean;\r\n\r\n reason?: string;\r\n };\r\n}\r\n\r\nexport interface SchemaV1Policy {\r\n schemaVersion: string;\r\n\r\n signalsSchema:\r\n Record<string, unknown>;\r\n\r\n rules: PolicyRule[];\r\n}\r\n\r\nfunction evaluateCondition(\r\n condition: RuleCondition,\r\n signals: Record<string, unknown>\r\n): boolean {\r\n\r\n if (\"all\" in condition) {\r\n return condition.all.every(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n if (\"any\" in condition) {\r\n return condition.any.some(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n const {\r\n signal,\r\n equals,\r\n greater_than,\r\n less_than,\r\n } = condition;\r\n\r\n if (!(signal in signals)) {\r\n\r\n throw new Error(\r\n `Signal not found: ${signal}`\r\n );\r\n }\r\n\r\n const actual =\r\n signals[signal];\r\n\r\n if (equals !== undefined) {\r\n\r\n return schemaV1Operators.equals(\r\n actual,\r\n equals\r\n );\r\n }\r\n\r\n if (\r\n greater_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.greater_than(\r\n actual as number,\r\n greater_than\r\n );\r\n }\r\n\r\n if (\r\n less_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.less_than(\r\n actual as number,\r\n less_than\r\n );\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function evaluateSchemaV1(\r\n policy: SchemaV1Policy,\r\n signals: Record<string, unknown>\r\n): DecisionResult {\r\n\r\n for (const rule of policy.rules) {\r\n\r\n const matched =\r\n evaluateCondition(\r\n rule.condition,\r\n signals\r\n );\r\n\r\n if (matched) {\r\n\r\n return {\r\n status: \"decided\",\r\n\r\n outcome:\r\n rule.outcome,\r\n\r\n rule_id:\r\n rule.id,\r\n\r\n source:\r\n \"rule_match\",\r\n };\r\n }\r\n }\r\n\r\n throw new Error(\r\n \"[SYS-006] No rule matched — policy must cover all cases\"\r\n );\r\n}\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n evaluateSchemaV1\r\n} from \"./v1/evaluator.js\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./v1/operators.js\";\r\n\r\nimport {\r\n schemaV1Semantics\r\n} from \"./v1/semantics.js\";\r\n\r\nexport interface SchemaRuntime {\r\n\r\n semantics: unknown;\r\n\r\n operators: unknown;\r\n\r\n evaluate: (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult;\r\n}\r\n\r\nexport function loadSchemaRuntime(\r\n schemaVersion: string\r\n): SchemaRuntime {\r\n\r\n const major =\r\n Number(\r\n schemaVersion.split(\".\")[0]\r\n );\r\n\r\n switch (major) {\r\n\r\n case 1:\r\n\r\n return {\r\n\r\n semantics:\r\n schemaV1Semantics,\r\n\r\n operators:\r\n schemaV1Operators,\r\n\r\n evaluate:\r\n evaluateSchemaV1 as (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult,\r\n };\r\n\r\n default:\r\n\r\n throw new Error(\r\n `Unsupported schema version: ${schemaVersion}`\r\n );\r\n }\r\n}\r\n"],"mappings":"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","names":["path","fs","path","fs","path"]}
1
+ {"version":3,"sources":["../src/compile-policy.ts","../src/create-policy.ts","../src/generate-bundle.ts","../src/upgrade-policy.ts","../src/validate-policy.ts","../src/define-policy.ts","../src/schema/v1/semantics.ts","../src/schema/v1/operators.ts","../src/schema/v1/evaluator.ts","../src/schema/load-schema-runtime.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nexport interface PolicyCompileError {\n code: string;\n message: string;\n field?: string;\n}\n\nexport interface PolicyCompileWarning {\n code: string;\n message: string;\n}\n\nexport interface PolicyCompileResult {\n valid: boolean;\n policyId: string;\n policyVersion: string;\n path: string;\n errors: PolicyCompileError[];\n warnings: PolicyCompileWarning[];\n}\n\nconst SUPPORTED_SCHEMA_VERSIONS = [\"1.0.0\"];\n\nconst VALID_SIGNAL_TYPES = [\n \"integer\",\n \"number\",\n \"boolean\",\n \"string\",\n \"enum\",\n];\n\nconst VALID_ACTIONS = [\n \"approve\",\n \"reject\",\n \"escalate\",\n \"manual_review\",\n \"document_required\",\n \"auto_approve\",\n \"fraud_review\",\n \"pending_override\",\n];\n\nfunction extractSignalRefs(condition: unknown): string[] {\n if (!condition || typeof condition !== \"object\" || Array.isArray(condition)) {\n return [];\n }\n const c = condition as Record<string, unknown>;\n if (typeof c.signal === \"string\") return [c.signal];\n if (Array.isArray(c.all)) return c.all.flatMap(extractSignalRefs);\n if (Array.isArray(c.any)) return c.any.flatMap(extractSignalRefs);\n return [];\n}\n\nfunction isCatchAll(condition: unknown): boolean {\n if (!condition || typeof condition !== \"object\" || Array.isArray(condition)) {\n return false;\n }\n const c = condition as Record<string, unknown>;\n return \"all\" in c && Array.isArray(c.all) && c.all.length === 0;\n}\n\nexport function compilePolicy(policyDirectory: string): PolicyCompileResult {\n const errors: PolicyCompileError[] = [];\n const warnings: PolicyCompileWarning[] = [];\n\n let policyId = \"\";\n let policyVersion = \"\";\n\n const err = (code: string, message: string, field?: string) =>\n errors.push({ code, message, ...(field ? { field } : {}) });\n const warn = (code: string, message: string) =>\n warnings.push({ code, message });\n\n // ── PHASE 1 — File exists ──────────────────────────────────────────────────\n const policyFile = path.join(policyDirectory, \"policy.json\");\n if (!fs.existsSync(policyFile)) {\n err(\"POL-001\", `policy.json not found at ${policyFile}`);\n return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };\n }\n\n // ── PHASE 2 — Valid JSON ───────────────────────────────────────────────────\n let content: Record<string, unknown>;\n try {\n const raw = fs.readFileSync(policyFile, \"utf8\");\n const parsed: unknown = JSON.parse(raw);\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n err(\"POL-002\", \"Invalid JSON: expected object at top level\");\n return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };\n }\n content = parsed as Record<string, unknown>;\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n err(\"POL-002\", `Invalid JSON: ${msg}`);\n return { valid: false, policyId, policyVersion, path: policyDirectory, errors, warnings };\n }\n\n // ── PHASE 3 — Required fields ──────────────────────────────────────────────\n if (!content.policyId || typeof content.policyId !== \"string\") {\n err(\"POL-003\", \"Missing required field: policyId\", \"policyId\");\n } else {\n policyId = content.policyId;\n }\n\n if (!content.policyVersion || typeof content.policyVersion !== \"string\") {\n err(\"POL-004\", \"Missing required field: policyVersion\", \"policyVersion\");\n } else {\n policyVersion = content.policyVersion;\n }\n\n if (!content.schemaVersion || typeof content.schemaVersion !== \"string\") {\n err(\"POL-005\", \"Missing required field: schemaVersion\", \"schemaVersion\");\n }\n\n if (\n content.signalsSchema === null ||\n content.signalsSchema === undefined ||\n typeof content.signalsSchema !== \"object\" ||\n Array.isArray(content.signalsSchema)\n ) {\n err(\"POL-006\", \"Missing required field: signalsSchema\", \"signalsSchema\");\n }\n\n if (!Array.isArray(content.rules)) {\n err(\"POL-007\", \"Missing required field: rules\", \"rules\");\n }\n\n // ── PHASE 4 — policyId matches directory structure ─────────────────────────\n if (policyId) {\n const dirPolicyId = path.basename(path.dirname(policyDirectory));\n if (dirPolicyId !== policyId) {\n warn(\n \"POL-008\",\n `policyId in policy.json does not match directory name (directory: '${dirPolicyId}', policyId: '${policyId}')`,\n );\n }\n }\n\n // ── PHASE 5 — schemaVersion is supported ──────────────────────────────────\n if (content.schemaVersion && typeof content.schemaVersion === \"string\") {\n if (!SUPPORTED_SCHEMA_VERSIONS.includes(content.schemaVersion)) {\n err(\n \"POL-009\",\n `Unsupported schemaVersion: ${content.schemaVersion}. Supported: ${SUPPORTED_SCHEMA_VERSIONS.join(\", \")}`,\n \"schemaVersion\",\n );\n }\n }\n\n // ── PHASE 6 — signalsSchema field validation ───────────────────────────────\n const signalsSchema = content.signalsSchema as Record<string, unknown> | undefined;\n const knownSignals = new Set<string>();\n\n if (signalsSchema && typeof signalsSchema === \"object\" && !Array.isArray(signalsSchema)) {\n for (const [name, def] of Object.entries(signalsSchema)) {\n knownSignals.add(name);\n\n if (!def || typeof def !== \"object\" || Array.isArray(def)) {\n err(\"POL-010\", `Signal '${name}' missing required 'type' field`, name);\n continue;\n }\n\n const d = def as Record<string, unknown>;\n\n if (!d.type || typeof d.type !== \"string\") {\n err(\"POL-010\", `Signal '${name}' missing required 'type' field`, name);\n continue;\n }\n\n if (!VALID_SIGNAL_TYPES.includes(d.type)) {\n err(\n \"POL-011\",\n `Signal '${name}' has invalid type '${d.type}'. Valid: ${VALID_SIGNAL_TYPES.join(\", \")}`,\n name,\n );\n }\n\n if (d.type === \"enum\") {\n if (!Array.isArray(d.values) || (d.values as unknown[]).length === 0) {\n err(\"POL-012\", `Signal '${name}' type 'enum' requires non-empty 'values' array`, name);\n }\n }\n }\n }\n\n // ── PHASE 7 — rules validation ─────────────────────────────────────────────\n const rules = content.rules;\n\n if (Array.isArray(rules)) {\n const seenIds = new Set<string>();\n\n for (let i = 0; i < rules.length; i++) {\n const rule = rules[i] as Record<string, unknown>;\n\n if (!rule || typeof rule !== \"object\") {\n err(\"POL-013\", `Rule at index ${i} missing required 'id' field`);\n continue;\n }\n\n const ruleId =\n typeof rule.id === \"string\" && rule.id.length > 0 ? rule.id : null;\n\n if (!ruleId) {\n err(\"POL-013\", `Rule at index ${i} missing required 'id' field`);\n continue;\n }\n\n if (seenIds.has(ruleId)) {\n err(\"POL-020\", `Duplicate rule id: '${ruleId}'`);\n } else {\n seenIds.add(ruleId);\n }\n\n if (!rule.condition || typeof rule.condition !== \"object\" || Array.isArray(rule.condition)) {\n err(\"POL-014\", `Rule '${ruleId}' missing required 'condition' field`);\n } else {\n for (const ref of extractSignalRefs(rule.condition)) {\n if (knownSignals.size > 0 && !knownSignals.has(ref)) {\n warn(\"POL-019\", `Rule '${ruleId}' references signal '${ref}' not in signalsSchema`);\n }\n }\n }\n\n if (!rule.outcome || typeof rule.outcome !== \"object\" || Array.isArray(rule.outcome)) {\n err(\"POL-015\", `Rule '${ruleId}' missing required 'outcome' field`);\n } else {\n const outcome = rule.outcome as Record<string, unknown>;\n\n if (!outcome.action || !VALID_ACTIONS.includes(outcome.action as string)) {\n err(\n \"POL-016\",\n `Rule '${ruleId}' outcome.action '${outcome.action}' is not a valid action`,\n );\n }\n\n if (typeof outcome.requires_override !== \"boolean\") {\n err(\"POL-017\", `Rule '${ruleId}' outcome.requires_override must be boolean`);\n }\n\n if (outcome.reason !== undefined && typeof outcome.reason !== \"string\") {\n err(\"POL-018\", `Rule '${ruleId}' outcome.reason must be string`);\n }\n }\n }\n\n // ── PHASE 8 — Catch-all rule ───────────────────────────────────────────\n const hasCatchAll = rules.some(r => isCatchAll((r as Record<string, unknown>).condition));\n if (!hasCatchAll) {\n warn(\n \"POL-021\",\n \"No catch-all rule found. Executions with unmatched signals will use default reject.\",\n );\n }\n }\n\n return {\n valid: errors.length === 0,\n policyId,\n policyVersion,\n path: policyDirectory,\n errors,\n warnings,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Scaffolds a new policy directory at `./policies/<policyId>/1.0.0/` and writes\n * a skeleton `policy.json` to it.\n *\n * @param policyId - Unique policy identifier. Must not already exist on disk.\n * @returns Absolute path of the created `1.0.0` version directory.\n * @throws When `./policies/<policyId>` already exists.\n */\nexport function createPolicy(\n policyId: string\n): string {\n const policyRoot = path.join(\n \"./policies\",\n policyId\n );\n\n const versionDirectory =\n path.join(\n policyRoot,\n \"1.0.0\"\n );\n\n if (fs.existsSync(policyRoot)) {\n throw new Error(\n `Policy already exists: ${policyId}`\n );\n }\n\n fs.mkdirSync(\n versionDirectory,\n {\n recursive: true,\n }\n );\n\n fs.writeFileSync(\n path.join(\n versionDirectory,\n \"policy.json\"\n ),\n\n JSON.stringify(\n {\n policyId,\n policyVersion: \"1.0.0\",\n schemaVersion: \"1.0.0\",\n signalsSchema: {},\n rules: [],\n },\n null,\n 2\n ),\n\n \"utf8\"\n );\n\n return versionDirectory;\n}\n","import * as path from \"node:path\";\r\n\r\nimport {\r\n generateManifest,\r\n writeManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n signManifest,\r\n writeSignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\nimport type {\r\n BundleGenerationResult,\r\n} from \"./types.js\";\r\n\r\nimport {\r\n compilePolicy,\r\n} from \"./compile-policy.js\";\r\n\r\n/**\r\n * Signer configuration for {@link generateBundle}.\r\n * Provide an explicit private key path — never rely on implicit trust key discovery.\r\n */\r\nexport interface BundleSigner {\r\n /** Absolute or CWD-relative path to the PEM-encoded Ed25519 private key. */\r\n privateKeyPath: string;\r\n}\r\n\r\n/**\r\n * Generates a content-addressed bundle for `policyId`/`policyVersion` in `policyDirectory`:\r\n * 1. Hashes all artifacts and writes `bundle.manifest.json`.\r\n * 2. If `signer` is provided: signs the manifest and writes `bundle.sig`.\r\n * If no signer: produces an unsigned bundle (`bundle.sig` is not written).\r\n *\r\n * Unsigned bundles are valid for development.\r\n * Production deployments should provide a signer.\r\n *\r\n * @param policyId - Policy identifier embedded in the manifest.\r\n * @param policyVersion - Policy version string (e.g. `\"v1\"`).\r\n * @param policyDirectory - Path to the directory containing the policy artifacts.\r\n * @param signer - Optional signing configuration. Omit to produce an unsigned bundle.\r\n * @returns Paths to the written files and the deterministic bundle hash.\r\n */\r\nexport function generateBundle(\r\n policyId: string,\r\n policyVersion: string,\r\n policyDirectory: string,\r\n signer?: BundleSigner\r\n): BundleGenerationResult {\r\n\r\n const directory =\r\n path.resolve(\r\n policyDirectory\r\n );\r\n\r\n // Validate policy before signing — cannot sign an invalid policy\r\n const compileResult = compilePolicy(directory);\r\n\r\n if (compileResult.errors.length > 0) {\r\n const messages = compileResult.errors\r\n .map(e => ` ${e.code}: ${e.message}`)\r\n .join(\"\\n\");\r\n throw new Error(\r\n `Policy validation failed — cannot generate bundle:\\n${messages}`,\r\n );\r\n }\r\n\r\n for (const w of compileResult.warnings) {\r\n console.warn(`[policy-compiler] ${w.code}: ${w.message}`);\r\n }\r\n\r\n const manifest =\r\n generateManifest(\r\n policyId,\r\n policyVersion,\r\n directory\r\n );\r\n\r\n writeManifest(\r\n manifest,\r\n directory\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n directory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (signer) {\r\n const signature =\r\n signManifest(\r\n manifestPath,\r\n signer.privateKeyPath\r\n );\r\n\r\n writeSignature(\r\n signature,\r\n directory\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n\r\n manifest_path:\r\n manifestPath,\r\n\r\n signature_path:\r\n signer\r\n ? path.join(directory, \"bundle.sig\")\r\n : null,\r\n\r\n bundle_hash:\r\n manifest.bundle_hash,\r\n };\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Creates the next version directory for `policyId` by copying the latest\n * existing version and incrementing it. Supports both semver (1.0.0) and\n * legacy v-prefix (v1) directory formats. The copied `policy.json` has its\n * version field updated to the new version string.\n *\n * @param policyId - An existing policy identifier under `./policies/`.\n * @returns Absolute path of the newly created version directory.\n * @throws When the policy does not exist on disk.\n */\nexport function upgradePolicy(\n policyId: string\n): string {\n const policyRoot = path.join(\n \"./policies\",\n policyId\n );\n\n if (!fs.existsSync(policyRoot)) {\n throw new Error(\n `Policy does not exist: ${policyId}`\n );\n }\n\n const allDirs = fs.readdirSync(policyRoot);\n\n // Accept semver (1.0.0) and legacy v-prefix (v1) formats\n const versions = allDirs.filter(\n (e) => /^\\d+\\.\\d+\\.\\d+$/.test(e) || /^v\\d+$/.test(e)\n );\n\n if (versions.length === 0) {\n throw new Error(\n `No version directories found for policy: ${policyId}`\n );\n }\n\n const parse = (v: string) =>\n v.replace(/^v/, \"\").split(\".\").map(Number);\n\n versions.sort((a, b) => {\n const [aMaj, aMin = 0, aPatch = 0] = parse(a);\n const [bMaj, bMin = 0, bPatch = 0] = parse(b);\n return aMaj !== bMaj ? aMaj - bMaj :\n aMin !== bMin ? aMin - bMin :\n aPatch - bPatch;\n });\n\n const latestVersion =\n versions[versions.length - 1];\n\n let nextVersion: string;\n\n if (/^\\d+\\.\\d+\\.\\d+$/.test(latestVersion)) {\n const [maj, min, patch] = latestVersion.split(\".\").map(Number);\n nextVersion = `${maj}.${min}.${patch + 1}`;\n } else {\n const latestNumber = Number(latestVersion.replace(\"v\", \"\"));\n nextVersion = `v${latestNumber + 1}`;\n }\n\n const latestDirectory =\n path.join(policyRoot, latestVersion);\n\n const nextDirectory =\n path.join(policyRoot, nextVersion);\n\n fs.cpSync(latestDirectory, nextDirectory, { recursive: true });\n\n const policyFile = path.join(nextDirectory, \"policy.json\");\n\n const content = JSON.parse(\n fs.readFileSync(policyFile, \"utf8\")\n );\n\n if (\"policyVersion\" in content) {\n content.policyVersion = nextVersion;\n } else {\n content.version = nextVersion;\n }\n\n fs.writeFileSync(\n policyFile,\n JSON.stringify(content, null, 2),\n \"utf8\"\n );\n\n return nextDirectory;\n}\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\nimport {\r\n readManifest,\r\n verifyManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n readSignature,\r\n verifySignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\n/**\r\n * Validates every version directory under `./policies/<policyId>` by\r\n * re-verifying all bundle manifests (content hashes) and, when a public key\r\n * path is provided, cryptographic signatures (bundle.sig).\r\n *\r\n * - Version directories without a `bundle.manifest.json` (not yet bundled) are skipped.\r\n * - Version directories without a `bundle.sig` skip signature verification.\r\n * - When `publicKeyPath` is omitted, signature verification is skipped for all versions.\r\n *\r\n * Returns `true` only when every bundled version passes all applicable checks.\r\n *\r\n * @param policyId - Policy identifier whose version directories will be checked.\r\n * @param publicKeyPath - Optional explicit path to the PEM-encoded public key for\r\n * signature verification. When omitted, only manifest content\r\n * hashes are verified.\r\n * @throws When the policy directory does not exist.\r\n */\r\nexport function validatePolicy(\r\n policyId: string,\r\n publicKeyPath?: string\r\n): boolean {\r\n\r\n const policyRoot =\r\n path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n policyRoot\r\n )\r\n ) {\r\n throw new Error(\r\n `Policy does not exist: ${policyId}`\r\n );\r\n }\r\n\r\n const versions =\r\n fs\r\n .readdirSync(\r\n policyRoot\r\n )\r\n .filter(\r\n (entry) =>\r\n entry.startsWith(\"v\")\r\n )\r\n .sort();\r\n\r\n for (const version of versions) {\r\n\r\n const versionDirectory =\r\n path.join(\r\n policyRoot,\r\n version\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n manifestPath\r\n )\r\n ) {\r\n continue;\r\n }\r\n\r\n const manifest =\r\n readManifest(\r\n versionDirectory\r\n );\r\n\r\n const manifestResult =\r\n verifyManifest(\r\n manifest,\r\n versionDirectory\r\n );\r\n\r\n if (\r\n !manifestResult.valid\r\n ) {\r\n return false;\r\n }\r\n\r\n const sigPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.sig\"\r\n );\r\n\r\n if (\r\n !publicKeyPath ||\r\n !fs.existsSync(sigPath)\r\n ) {\r\n continue;\r\n }\r\n\r\n const signature =\r\n readSignature(\r\n versionDirectory\r\n );\r\n\r\n const signatureValid =\r\n verifySignature(\r\n manifestPath,\r\n signature,\r\n publicKeyPath\r\n );\r\n\r\n if (\r\n !signatureValid\r\n ) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n\r\n\r\n\r\n","import type {\r\n PolicyDefinition,\r\n PolicyRule,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Constructs a {@link PolicyDefinition} from a plain config object.\r\n * Use this as the first step in the policy-authoring pipeline before\r\n * serializing the policy to disk and calling {@link generateBundle}.\r\n *\r\n * @param config - Policy id, version, and rules.\r\n */\r\nexport function definePolicy(config: {\r\n id: string;\r\n version: string;\r\n rules: PolicyRule[];\r\n}): PolicyDefinition {\r\n\r\n return {\r\n id: config.id,\r\n\r\n version: config.version,\r\n\r\n rules: config.rules,\r\n };\r\n}\r\n","export const schemaV1Semantics = {\r\n\r\n schemaVersion:\r\n \"1.0.0\",\r\n\r\n ruleConditionField:\r\n \"condition\",\r\n\r\n ruleOutcomeField:\r\n \"outcome\",\r\n\r\n signalReferenceField:\r\n \"signal\",\r\n\r\n supportedOperators: [\r\n \"equals\",\r\n \"greater_than\",\r\n \"less_than\",\r\n ],\r\n};\r\n","export const schemaV1Operators = {\r\n\r\n equals(\r\n left: unknown,\r\n right: unknown\r\n ): boolean {\r\n\r\n return left === right;\r\n },\r\n\r\n greater_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left > right;\r\n },\r\n\r\n less_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left < right;\r\n },\r\n};\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./operators.js\";\r\n\r\ninterface BaseCondition {\r\n signal: string;\r\n equals?: unknown;\r\n greater_than?: number;\r\n less_than?: number;\r\n}\r\n\r\ninterface AllCondition {\r\n all: RuleCondition[];\r\n}\r\n\r\ninterface AnyCondition {\r\n any: RuleCondition[];\r\n}\r\n\r\ntype RuleCondition =\r\n | BaseCondition\r\n | AllCondition\r\n | AnyCondition;\r\n\r\ninterface PolicyRule {\r\n id: string;\r\n\r\n condition: RuleCondition;\r\n\r\n outcome: {\r\n action:\r\n | \"approve\"\r\n | \"reject\";\r\n\r\n requires_override:\r\n boolean;\r\n\r\n reason?: string;\r\n };\r\n}\r\n\r\nexport interface SchemaV1Policy {\r\n schemaVersion: string;\r\n\r\n signalsSchema:\r\n Record<string, unknown>;\r\n\r\n rules: PolicyRule[];\r\n}\r\n\r\nfunction evaluateCondition(\r\n condition: RuleCondition,\r\n signals: Record<string, unknown>\r\n): boolean {\r\n\r\n if (\"all\" in condition) {\r\n return condition.all.every(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n if (\"any\" in condition) {\r\n return condition.any.some(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n const {\r\n signal,\r\n equals,\r\n greater_than,\r\n less_than,\r\n } = condition;\r\n\r\n if (!(signal in signals)) {\r\n\r\n throw new Error(\r\n `Signal not found: ${signal}`\r\n );\r\n }\r\n\r\n const actual =\r\n signals[signal];\r\n\r\n if (equals !== undefined) {\r\n\r\n return schemaV1Operators.equals(\r\n actual,\r\n equals\r\n );\r\n }\r\n\r\n if (\r\n greater_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.greater_than(\r\n actual as number,\r\n greater_than\r\n );\r\n }\r\n\r\n if (\r\n less_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.less_than(\r\n actual as number,\r\n less_than\r\n );\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function evaluateSchemaV1(\r\n policy: SchemaV1Policy,\r\n signals: Record<string, unknown>\r\n): DecisionResult {\r\n\r\n for (const rule of policy.rules) {\r\n\r\n const matched =\r\n evaluateCondition(\r\n rule.condition,\r\n signals\r\n );\r\n\r\n if (matched) {\r\n\r\n return {\r\n status: \"decided\",\r\n\r\n outcome:\r\n rule.outcome,\r\n\r\n rule_id:\r\n rule.id,\r\n\r\n source:\r\n \"rule_match\",\r\n };\r\n }\r\n }\r\n\r\n return {\r\n status: \"decided\",\r\n outcome: {\r\n action: \"reject\",\r\n requires_override: false,\r\n reason: \"[SYS-006] No rule matched — default reject. Add a catch-all rule to make this explicit.\",\r\n },\r\n rule_id: \"default\",\r\n source: \"rule_match\",\r\n };\r\n}\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n evaluateSchemaV1\r\n} from \"./v1/evaluator.js\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./v1/operators.js\";\r\n\r\nimport {\r\n schemaV1Semantics\r\n} from \"./v1/semantics.js\";\r\n\r\nexport interface SchemaRuntime {\r\n\r\n semantics: unknown;\r\n\r\n operators: unknown;\r\n\r\n evaluate: (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult;\r\n}\r\n\r\nconst SUPPORTED_SCHEMA_VERSIONS: Record<string, SchemaRuntime> = {\r\n \"1.0.0\": {\r\n semantics: schemaV1Semantics,\r\n operators: schemaV1Operators,\r\n evaluate: evaluateSchemaV1 as (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult,\r\n },\r\n};\r\n\r\nexport function loadSchemaRuntime(\r\n schemaVersion: string\r\n): SchemaRuntime {\r\n\r\n const runtime = SUPPORTED_SCHEMA_VERSIONS[schemaVersion];\r\n\r\n if (!runtime) {\r\n throw new Error(\r\n `Unsupported schema version: ${schemaVersion}. Supported: ${Object.keys(SUPPORTED_SCHEMA_VERSIONS).join(\", \")}`\r\n );\r\n }\r\n\r\n return runtime;\r\n}\r\n"],"mappings":"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","names":["fs","path","path","fs","path","fs","path","SUPPORTED_SCHEMA_VERSIONS"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parmanasystems/governance",
3
- "version": "1.71.26",
3
+ "version": "1.71.38",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -18,9 +18,9 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "@parmanasystems/bundle": "^1.71.26",
22
- "@parmanasystems/crypto": "^1.71.26",
23
- "@parmanasystems/contracts": "^1.71.26"
21
+ "@parmanasystems/bundle": "^1.71.38",
22
+ "@parmanasystems/crypto": "^1.71.38",
23
+ "@parmanasystems/contracts": "^1.71.38"
24
24
  },
25
25
  "description": "Deterministic governance lifecycle and policy infrastructure for parmanasystems.",
26
26
  "license": "Apache-2.0",