@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 +25 -6
- package/dist/index.js +294 -82
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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>/
|
|
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 `
|
|
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
|
|
78
|
-
* The copied `policy.json` has its
|
|
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/
|
|
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 =
|
|
198
|
+
const policyRoot = path2.join(
|
|
6
199
|
"./policies",
|
|
7
200
|
policyId
|
|
8
201
|
);
|
|
9
|
-
const versionDirectory =
|
|
202
|
+
const versionDirectory = path2.join(
|
|
10
203
|
policyRoot,
|
|
11
|
-
"
|
|
204
|
+
"1.0.0"
|
|
12
205
|
);
|
|
13
|
-
if (
|
|
206
|
+
if (fs2.existsSync(policyRoot)) {
|
|
14
207
|
throw new Error(
|
|
15
208
|
`Policy already exists: ${policyId}`
|
|
16
209
|
);
|
|
17
210
|
}
|
|
18
|
-
|
|
211
|
+
fs2.mkdirSync(
|
|
19
212
|
versionDirectory,
|
|
20
213
|
{
|
|
21
214
|
recursive: true
|
|
22
215
|
}
|
|
23
216
|
);
|
|
24
|
-
|
|
25
|
-
|
|
217
|
+
fs2.writeFileSync(
|
|
218
|
+
path2.join(
|
|
26
219
|
versionDirectory,
|
|
27
220
|
"policy.json"
|
|
28
221
|
),
|
|
29
222
|
JSON.stringify(
|
|
30
223
|
{
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 ?
|
|
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
|
|
89
|
-
import * as
|
|
295
|
+
import * as fs3 from "fs";
|
|
296
|
+
import * as path4 from "path";
|
|
90
297
|
function upgradePolicy(policyId) {
|
|
91
|
-
const policyRoot =
|
|
298
|
+
const policyRoot = path4.join(
|
|
92
299
|
"./policies",
|
|
93
300
|
policyId
|
|
94
301
|
);
|
|
95
|
-
if (!
|
|
302
|
+
if (!fs3.existsSync(policyRoot)) {
|
|
96
303
|
throw new Error(
|
|
97
304
|
`Policy does not exist: ${policyId}`
|
|
98
305
|
);
|
|
99
306
|
}
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
129
|
-
policyFile,
|
|
130
|
-
"utf8"
|
|
131
|
-
)
|
|
336
|
+
fs3.readFileSync(policyFile, "utf8")
|
|
132
337
|
);
|
|
133
|
-
content
|
|
134
|
-
|
|
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
|
|
148
|
-
import * as
|
|
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 =
|
|
363
|
+
const policyRoot = path5.join(
|
|
159
364
|
"./policies",
|
|
160
365
|
policyId
|
|
161
366
|
);
|
|
162
|
-
if (!
|
|
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 =
|
|
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 =
|
|
380
|
+
const versionDirectory = path5.join(
|
|
176
381
|
policyRoot,
|
|
177
382
|
version
|
|
178
383
|
);
|
|
179
|
-
const manifestPath =
|
|
384
|
+
const manifestPath = path5.join(
|
|
180
385
|
versionDirectory,
|
|
181
386
|
"bundle.manifest.json"
|
|
182
387
|
);
|
|
183
|
-
if (!
|
|
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 =
|
|
403
|
+
const sigPath = path5.join(
|
|
199
404
|
versionDirectory,
|
|
200
405
|
"bundle.sig"
|
|
201
406
|
);
|
|
202
|
-
if (!publicKeyPath || !
|
|
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
|
-
|
|
321
|
-
|
|
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
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
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":";AAAA,YAAY,QAAQ;AACpB,YAAY,UAAU;AAUf,SAAS,aACd,UACQ;AACR,QAAM,aAAkB;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAEA,QAAM,mBACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,MAAO,cAAW,UAAU,GAAG;AAC7B,UAAM,IAAI;AAAA,MACR,0BAA0B,QAAQ;AAAA,IACpC;AAAA,EACF;AAEA,EAAG;AAAA,IACD;AAAA,IACA;AAAA,MACE,WAAW;AAAA,IACb;AAAA,EACF;AAEA,EAAG;AAAA,IACI;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,IAEA,KAAK;AAAA,MACH;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IAEA;AAAA,EACF;AAEA,SAAO;AACT;;;ACzDA,YAAYA,WAAU;AAEtB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AA8BA,SAAS,eACd,UACA,eACA,iBACA,QACwB;AAExB,QAAM,YACC;AAAA,IACH;AAAA,EACF;AAEF,QAAM,WACJ;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEF;AAAA,IACE;AAAA,IACA;AAAA,EACF;AAEA,QAAM,eACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,MAAI,QAAQ;AACV,UAAM,YACJ;AAAA,MACE;AAAA,MACA,OAAO;AAAA,IACT;AAEF;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IAET,eACE;AAAA,IAEF,gBACE,SACS,WAAK,WAAW,YAAY,IACjC;AAAA,IAEN,aACE,SAAS;AAAA,EACb;AACF;;;ACjGA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAYf,SAAS,cACd,UACQ;AACR,QAAM,aAAkB;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAI,eAAW,UAAU,GAAG;AAC9B,UAAM,IAAI;AAAA,MACR,0BAA0B,QAAQ;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,WACH,gBAAY,UAAU,EACtB;AAAA,IAAO,CAAC,UACP,MAAM,WAAW,GAAG;AAAA,EACtB,EACC,KAAK;AAER,QAAM,gBACJ,SACE,SAAS,SAAS,CACpB;AAEF,QAAM,eACJ;AAAA,IACE,cAAc,QAAQ,KAAK,EAAE;AAAA,EAC/B;AAEF,QAAM,cACJ,IAAI,eAAe,CAAC;AAEtB,QAAM,kBACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,QAAM,gBACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,EAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,MACE,WAAW;AAAA,IACb;AAAA,EACF;AAEA,QAAM,aACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,QAAM,UACJ,KAAK;AAAA,IACA;AAAA,MACD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEF,UAAQ,UACN;AAEF,EAAG;AAAA,IACD;AAAA,IACA,KAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AC/FA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AAEtB;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAmBA,SAAS,eACd,UACA,eACS;AAET,QAAM,aACC;AAAA,IACH;AAAA,IACA;AAAA,EACF;AAEF,MACE,CAAI;AAAA,IACF;AAAA,EACF,GACA;AACA,UAAM,IAAI;AAAA,MACR,0BAA0B,QAAQ;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,WAED;AAAA,IACC;AAAA,EACF,EACC;AAAA,IACC,CAAC,UACC,MAAM,WAAW,GAAG;AAAA,EACxB,EACC,KAAK;AAEV,aAAW,WAAW,UAAU;AAE9B,UAAM,mBACC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAEF,UAAM,eACC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAEF,QACE,CAAI;AAAA,MACF;AAAA,IACF,GACA;AACA;AAAA,IACF;AAEA,UAAM,WACJ;AAAA,MACE;AAAA,IACF;AAEF,UAAM,iBACJ;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAEF,QACE,CAAC,eAAe,OAChB;AACA,aAAO;AAAA,IACT;AAEA,UAAM,UACC;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAEF,QACE,CAAC,iBACD,CAAI,eAAW,OAAO,GACtB;AACA;AAAA,IACF;AAEA,UAAM,YACJ;AAAA,MACE;AAAA,IACF;AAEF,UAAM,iBACJ;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEF,QACE,CAAC,gBACD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;;;AC1HO,SAAS,aAAa,QAIR;AAEnB,SAAO;AAAA,IACL,IAAI,OAAO;AAAA,IAEX,SAAS,OAAO;AAAA,IAEhB,OAAO,OAAO;AAAA,EAChB;AACF;;;ACzBO,IAAM,oBAAoB;AAAA,EAE/B,eACE;AAAA,EAEF,oBACE;AAAA,EAEF,kBACE;AAAA,EAEF,sBACE;AAAA,EAEF,oBAAoB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACnBO,IAAM,oBAAoB;AAAA,EAE/B,OACE,MACA,OACS;AAET,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,aACE,MACA,OACS;AAET,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,UACE,MACA,OACS;AAET,WAAO,OAAO;AAAA,EAChB;AACF;;;AC6BA,SAAS,kBACP,WACA,SACS;AAET,MAAI,SAAS,WAAW;AACtB,WAAO,UAAU,IAAI;AAAA,MACnB,OACE;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,SAAS,WAAW;AACtB,WAAO,UAAU,IAAI;AAAA,MACnB,OACE;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACJ;AAAA,EACF;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,MAAI,EAAE,UAAU,UAAU;AAExB,UAAM,IAAI;AAAA,MACR,qBAAqB,MAAM;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,SACJ,QAAQ,MAAM;AAEhB,MAAI,WAAW,QAAW;AAExB,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MACE,iBAAiB,QACjB;AAEA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MACE,cAAc,QACd;AAEA,WAAO,kBAAkB;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBACd,QACA,SACgB;AAEhB,aAAW,QAAQ,OAAO,OAAO;AAE/B,UAAM,UACJ;AAAA,MACE,KAAK;AAAA,MACL;AAAA,IACF;AAEF,QAAI,SAAS;AAEX,aAAO;AAAA,QACL,QAAQ;AAAA,QAER,SACE,KAAK;AAAA,QAEP,SACE,KAAK;AAAA,QAEP,QACE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;;;ACpIO,SAAS,kBACd,eACe;AAEf,QAAM,QACJ;AAAA,IACE,cAAc,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5B;AAEF,UAAQ,OAAO;AAAA,IAEb,KAAK;AAEH,aAAO;AAAA,QAEL,WACE;AAAA,QAEF,WACE;AAAA,QAEF,UACE;AAAA,MAIJ;AAAA,IAEF;AAEE,YAAM,IAAI;AAAA,QACR,+BAA+B,aAAa;AAAA,MAC9C;AAAA,EACJ;AACF;","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.
|
|
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.
|
|
22
|
-
"@parmanasystems/crypto": "^1.71.
|
|
23
|
-
"@parmanasystems/contracts": "^1.71.
|
|
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",
|