@parmanasystems/governance 1.71.36 → 1.74.0
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/README.md +12 -12
- package/dist/index.d.ts +22 -3
- package/dist/index.js +240 -35
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -30,19 +30,19 @@ import {
|
|
|
30
30
|
upgradePolicy,
|
|
31
31
|
} from "@parmanasystems/governance";
|
|
32
32
|
|
|
33
|
-
// Scaffold a new policy directory at ./policies/loan-approval/
|
|
33
|
+
// Scaffold a new policy directory at ./policies/loan-approval/1.0.0/
|
|
34
34
|
const dir = createPolicy("loan-approval");
|
|
35
|
-
console.log(dir); // "./policies/loan-approval/
|
|
36
|
-
// Edit ./policies/loan-approval/
|
|
35
|
+
console.log(dir); // "./policies/loan-approval/1.0.0"
|
|
36
|
+
// Edit ./policies/loan-approval/1.0.0/policy.json with your rules
|
|
37
37
|
|
|
38
38
|
// Validate policy files before bundling — throws on schema errors
|
|
39
|
-
validatePolicy("./policies/loan-approval/
|
|
39
|
+
validatePolicy("./policies/loan-approval/1.0.0");
|
|
40
40
|
|
|
41
41
|
// Package into a content-addressed bundle (unsigned — safe for development)
|
|
42
42
|
const result = generateBundle(
|
|
43
43
|
"loan-approval",
|
|
44
|
-
"
|
|
45
|
-
"./policies/loan-approval/
|
|
44
|
+
"1.0.0",
|
|
45
|
+
"./policies/loan-approval/1.0.0"
|
|
46
46
|
);
|
|
47
47
|
console.log(result.success); // true
|
|
48
48
|
console.log(result.bundle_hash); // SHA-256 commitment over all policy artifacts
|
|
@@ -59,11 +59,11 @@ import { generateBundle } from "@parmanasystems/governance";
|
|
|
59
59
|
|
|
60
60
|
const result = generateBundle(
|
|
61
61
|
"loan-approval",
|
|
62
|
-
"
|
|
63
|
-
"./policies/loan-approval/
|
|
62
|
+
"1.0.0",
|
|
63
|
+
"./policies/loan-approval/1.0.0",
|
|
64
64
|
{ privateKeyPath: "./trust/root.key" } // optional — omit for unsigned bundles
|
|
65
65
|
);
|
|
66
|
-
console.log(result.signature_path); // "./policies/loan-approval/
|
|
66
|
+
console.log(result.signature_path); // "./policies/loan-approval/1.0.0/bundle.sig"
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
### Upgrade an existing policy
|
|
@@ -71,9 +71,9 @@ console.log(result.signature_path); // "./policies/loan-approval/v1/bundle.sig"
|
|
|
71
71
|
```typescript
|
|
72
72
|
import { upgradePolicy } from "@parmanasystems/governance";
|
|
73
73
|
|
|
74
|
-
// Creates ./policies/loan-approval/
|
|
74
|
+
// Creates ./policies/loan-approval/2.0.0/ as a copy of 1.0.0 — edit the new version's rules
|
|
75
75
|
const newDir = upgradePolicy("loan-approval");
|
|
76
|
-
console.log(newDir); // "./policies/loan-approval/
|
|
76
|
+
console.log(newDir); // "./policies/loan-approval/2.0.0"
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
---
|
|
@@ -84,7 +84,7 @@ console.log(newDir); // "./policies/loan-approval/v2"
|
|
|
84
84
|
|
|
85
85
|
| Export | Description |
|
|
86
86
|
|---|---|
|
|
87
|
-
| `createPolicy` | Scaffold a new policy directory at `./policies/<id>/
|
|
87
|
+
| `createPolicy` | Scaffold a new policy directory at `./policies/<id>/1.0.0/` with a skeleton `policy.json` |
|
|
88
88
|
| `upgradePolicy` | Create the next version directory from the current latest version |
|
|
89
89
|
| `validatePolicy` | Validate a policy directory against the governance schema; throws on invalid input |
|
|
90
90
|
| `generateBundle` | Package a policy directory into a content-addressed bundle; optionally sign with a private key |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
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
23
|
* Scaffolds a new policy directory at `./policies/<policyId>/1.0.0/` and writes
|
|
5
24
|
* a skeleton `policy.json` to it.
|
|
@@ -41,7 +60,7 @@ interface PolicyRule$1 {
|
|
|
41
60
|
interface PolicyDefinition {
|
|
42
61
|
/** Policy identifier. */
|
|
43
62
|
id: string;
|
|
44
|
-
/** Semantic version string (e.g. `"
|
|
63
|
+
/** Semantic version string (e.g. `"1.0.0"`). */
|
|
45
64
|
version: string;
|
|
46
65
|
/** Ordered list of rules that make up the policy. */
|
|
47
66
|
rules: PolicyRule$1[];
|
|
@@ -65,7 +84,7 @@ interface BundleSigner {
|
|
|
65
84
|
* Production deployments should provide a signer.
|
|
66
85
|
*
|
|
67
86
|
* @param policyId - Policy identifier embedded in the manifest.
|
|
68
|
-
* @param policyVersion - Policy version string (e.g. `"
|
|
87
|
+
* @param policyVersion - Policy version string (e.g. `"1.0.0"`).
|
|
69
88
|
* @param policyDirectory - Path to the directory containing the policy artifacts.
|
|
70
89
|
* @param signer - Optional signing configuration. Omit to produce an unsigned bundle.
|
|
71
90
|
* @returns Paths to the written files and the deterministic bundle hash.
|
|
@@ -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,28 +1,221 @@
|
|
|
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
|
),
|
|
@@ -43,7 +236,7 @@ function createPolicy(policyId) {
|
|
|
43
236
|
}
|
|
44
237
|
|
|
45
238
|
// src/generate-bundle.ts
|
|
46
|
-
import * as
|
|
239
|
+
import * as path3 from "path";
|
|
47
240
|
import {
|
|
48
241
|
generateManifest,
|
|
49
242
|
writeManifest
|
|
@@ -53,9 +246,20 @@ import {
|
|
|
53
246
|
writeSignature
|
|
54
247
|
} from "@parmanasystems/crypto";
|
|
55
248
|
function generateBundle(policyId, policyVersion, policyDirectory, signer) {
|
|
56
|
-
const directory =
|
|
249
|
+
const directory = path3.resolve(
|
|
57
250
|
policyDirectory
|
|
58
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
|
+
}
|
|
59
263
|
const manifest = generateManifest(
|
|
60
264
|
policyId,
|
|
61
265
|
policyVersion,
|
|
@@ -65,7 +269,7 @@ function generateBundle(policyId, policyVersion, policyDirectory, signer) {
|
|
|
65
269
|
manifest,
|
|
66
270
|
directory
|
|
67
271
|
);
|
|
68
|
-
const manifestPath =
|
|
272
|
+
const manifestPath = path3.join(
|
|
69
273
|
directory,
|
|
70
274
|
"bundle.manifest.json"
|
|
71
275
|
);
|
|
@@ -82,25 +286,25 @@ function generateBundle(policyId, policyVersion, policyDirectory, signer) {
|
|
|
82
286
|
return {
|
|
83
287
|
success: true,
|
|
84
288
|
manifest_path: manifestPath,
|
|
85
|
-
signature_path: signer ?
|
|
289
|
+
signature_path: signer ? path3.join(directory, "bundle.sig") : null,
|
|
86
290
|
bundle_hash: manifest.bundle_hash
|
|
87
291
|
};
|
|
88
292
|
}
|
|
89
293
|
|
|
90
294
|
// src/upgrade-policy.ts
|
|
91
|
-
import * as
|
|
92
|
-
import * as
|
|
295
|
+
import * as fs3 from "fs";
|
|
296
|
+
import * as path4 from "path";
|
|
93
297
|
function upgradePolicy(policyId) {
|
|
94
|
-
const policyRoot =
|
|
298
|
+
const policyRoot = path4.join(
|
|
95
299
|
"./policies",
|
|
96
300
|
policyId
|
|
97
301
|
);
|
|
98
|
-
if (!
|
|
302
|
+
if (!fs3.existsSync(policyRoot)) {
|
|
99
303
|
throw new Error(
|
|
100
304
|
`Policy does not exist: ${policyId}`
|
|
101
305
|
);
|
|
102
306
|
}
|
|
103
|
-
const allDirs =
|
|
307
|
+
const allDirs = fs3.readdirSync(policyRoot);
|
|
104
308
|
const versions = allDirs.filter(
|
|
105
309
|
(e) => /^\d+\.\d+\.\d+$/.test(e) || /^v\d+$/.test(e)
|
|
106
310
|
);
|
|
@@ -124,19 +328,19 @@ function upgradePolicy(policyId) {
|
|
|
124
328
|
const latestNumber = Number(latestVersion.replace("v", ""));
|
|
125
329
|
nextVersion = `v${latestNumber + 1}`;
|
|
126
330
|
}
|
|
127
|
-
const latestDirectory =
|
|
128
|
-
const nextDirectory =
|
|
129
|
-
|
|
130
|
-
const policyFile =
|
|
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");
|
|
131
335
|
const content = JSON.parse(
|
|
132
|
-
|
|
336
|
+
fs3.readFileSync(policyFile, "utf8")
|
|
133
337
|
);
|
|
134
338
|
if ("policyVersion" in content) {
|
|
135
339
|
content.policyVersion = nextVersion;
|
|
136
340
|
} else {
|
|
137
341
|
content.version = nextVersion;
|
|
138
342
|
}
|
|
139
|
-
|
|
343
|
+
fs3.writeFileSync(
|
|
140
344
|
policyFile,
|
|
141
345
|
JSON.stringify(content, null, 2),
|
|
142
346
|
"utf8"
|
|
@@ -145,8 +349,8 @@ function upgradePolicy(policyId) {
|
|
|
145
349
|
}
|
|
146
350
|
|
|
147
351
|
// src/validate-policy.ts
|
|
148
|
-
import * as
|
|
149
|
-
import * as
|
|
352
|
+
import * as fs4 from "fs";
|
|
353
|
+
import * as path5 from "path";
|
|
150
354
|
import {
|
|
151
355
|
readManifest,
|
|
152
356
|
verifyManifest
|
|
@@ -156,32 +360,32 @@ import {
|
|
|
156
360
|
verifySignature
|
|
157
361
|
} from "@parmanasystems/crypto";
|
|
158
362
|
function validatePolicy(policyId, publicKeyPath) {
|
|
159
|
-
const policyRoot =
|
|
363
|
+
const policyRoot = path5.join(
|
|
160
364
|
"./policies",
|
|
161
365
|
policyId
|
|
162
366
|
);
|
|
163
|
-
if (!
|
|
367
|
+
if (!fs4.existsSync(
|
|
164
368
|
policyRoot
|
|
165
369
|
)) {
|
|
166
370
|
throw new Error(
|
|
167
371
|
`Policy does not exist: ${policyId}`
|
|
168
372
|
);
|
|
169
373
|
}
|
|
170
|
-
const versions =
|
|
374
|
+
const versions = fs4.readdirSync(
|
|
171
375
|
policyRoot
|
|
172
376
|
).filter(
|
|
173
377
|
(entry) => entry.startsWith("v")
|
|
174
378
|
).sort();
|
|
175
379
|
for (const version of versions) {
|
|
176
|
-
const versionDirectory =
|
|
380
|
+
const versionDirectory = path5.join(
|
|
177
381
|
policyRoot,
|
|
178
382
|
version
|
|
179
383
|
);
|
|
180
|
-
const manifestPath =
|
|
384
|
+
const manifestPath = path5.join(
|
|
181
385
|
versionDirectory,
|
|
182
386
|
"bundle.manifest.json"
|
|
183
387
|
);
|
|
184
|
-
if (!
|
|
388
|
+
if (!fs4.existsSync(
|
|
185
389
|
manifestPath
|
|
186
390
|
)) {
|
|
187
391
|
continue;
|
|
@@ -196,11 +400,11 @@ function validatePolicy(policyId, publicKeyPath) {
|
|
|
196
400
|
if (!manifestResult.valid) {
|
|
197
401
|
return false;
|
|
198
402
|
}
|
|
199
|
-
const sigPath =
|
|
403
|
+
const sigPath = path5.join(
|
|
200
404
|
versionDirectory,
|
|
201
405
|
"bundle.sig"
|
|
202
406
|
);
|
|
203
|
-
if (!publicKeyPath || !
|
|
407
|
+
if (!publicKeyPath || !fs4.existsSync(sigPath)) {
|
|
204
408
|
continue;
|
|
205
409
|
}
|
|
206
410
|
const signature = readSignature(
|
|
@@ -331,7 +535,7 @@ function evaluateSchemaV1(policy, signals) {
|
|
|
331
535
|
}
|
|
332
536
|
|
|
333
537
|
// src/schema/load-schema-runtime.ts
|
|
334
|
-
var
|
|
538
|
+
var SUPPORTED_SCHEMA_VERSIONS2 = {
|
|
335
539
|
"1.0.0": {
|
|
336
540
|
semantics: schemaV1Semantics,
|
|
337
541
|
operators: schemaV1Operators,
|
|
@@ -339,15 +543,16 @@ var SUPPORTED_SCHEMA_VERSIONS = {
|
|
|
339
543
|
}
|
|
340
544
|
};
|
|
341
545
|
function loadSchemaRuntime(schemaVersion) {
|
|
342
|
-
const runtime =
|
|
546
|
+
const runtime = SUPPORTED_SCHEMA_VERSIONS2[schemaVersion];
|
|
343
547
|
if (!runtime) {
|
|
344
548
|
throw new Error(
|
|
345
|
-
`Unsupported schema version: ${schemaVersion}. Supported: ${Object.keys(
|
|
549
|
+
`Unsupported schema version: ${schemaVersion}. Supported: ${Object.keys(SUPPORTED_SCHEMA_VERSIONS2).join(", ")}`
|
|
346
550
|
);
|
|
347
551
|
}
|
|
348
552
|
return runtime;
|
|
349
553
|
}
|
|
350
554
|
export {
|
|
555
|
+
compilePolicy,
|
|
351
556
|
createPolicy,
|
|
352
557
|
definePolicy,
|
|
353
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\";\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\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\";\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":["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. `\"1.0.0\"`).\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.
|
|
3
|
+
"version": "1.74.0",
|
|
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.
|
|
22
|
-
"@parmanasystems/crypto": "^1.
|
|
23
|
-
"@parmanasystems/contracts": "^1.
|
|
21
|
+
"@parmanasystems/bundle": "^1.74.0",
|
|
22
|
+
"@parmanasystems/crypto": "^1.74.0",
|
|
23
|
+
"@parmanasystems/contracts": "^1.74.0"
|
|
24
24
|
},
|
|
25
25
|
"description": "Deterministic governance lifecycle and policy infrastructure for parmanasystems.",
|
|
26
26
|
"license": "Apache-2.0",
|