@parmanasystems/governance 1.71.26 → 1.71.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { DecisionResult } from '@parmanasystems/contracts';
2
2
 
3
3
  /**
4
- * Scaffolds a new policy directory at `./policies/<policyId>/v1/` and writes
4
+ * Scaffolds a new policy directory at `./policies/<policyId>/1.0.0/` and writes
5
5
  * a skeleton `policy.json` to it.
6
6
  *
7
7
  * @param policyId - Unique policy identifier. Must not already exist on disk.
8
- * @returns Absolute path of the created `v1` version directory.
8
+ * @returns Absolute path of the created `1.0.0` version directory.
9
9
  * @throws When `./policies/<policyId>` already exists.
10
10
  */
11
11
  declare function createPolicy(policyId: string): string;
@@ -74,9 +74,9 @@ declare function generateBundle(policyId: string, policyVersion: string, policyD
74
74
 
75
75
  /**
76
76
  * Creates the next version directory for `policyId` by copying the latest
77
- * existing version and incrementing its numeric suffix (e.g. `v1` → `v2`).
78
- * The copied `policy.json` has its `version` field updated to the new version
79
- * string.
77
+ * existing version and incrementing it. Supports both semver (1.0.0) and
78
+ * legacy v-prefix (v1) directory formats. The copied `policy.json` has its
79
+ * version field updated to the new version string.
80
80
  *
81
81
  * @param policyId - An existing policy identifier under `./policies/`.
82
82
  * @returns Absolute path of the newly created version directory.
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ function createPolicy(policyId) {
8
8
  );
9
9
  const versionDirectory = path.join(
10
10
  policyRoot,
11
- "v1"
11
+ "1.0.0"
12
12
  );
13
13
  if (fs.existsSync(policyRoot)) {
14
14
  throw new Error(
@@ -28,8 +28,11 @@ function createPolicy(policyId) {
28
28
  ),
29
29
  JSON.stringify(
30
30
  {
31
- policy: policyId,
32
- version: "v1"
31
+ policyId,
32
+ policyVersion: "1.0.0",
33
+ schemaVersion: "1.0.0",
34
+ signalsSchema: {},
35
+ rules: []
33
36
  },
34
37
  null,
35
38
  2
@@ -97,47 +100,45 @@ function upgradePolicy(policyId) {
97
100
  `Policy does not exist: ${policyId}`
98
101
  );
99
102
  }
100
- const versions = fs2.readdirSync(policyRoot).filter(
101
- (entry) => entry.startsWith("v")
102
- ).sort();
103
- const latestVersion = versions[versions.length - 1];
104
- const latestNumber = Number(
105
- latestVersion.replace("v", "")
106
- );
107
- const nextVersion = `v${latestNumber + 1}`;
108
- const latestDirectory = path3.join(
109
- policyRoot,
110
- latestVersion
111
- );
112
- const nextDirectory = path3.join(
113
- policyRoot,
114
- nextVersion
115
- );
116
- fs2.cpSync(
117
- latestDirectory,
118
- nextDirectory,
119
- {
120
- recursive: true
121
- }
122
- );
123
- const policyFile = path3.join(
124
- nextDirectory,
125
- "policy.json"
103
+ const allDirs = fs2.readdirSync(policyRoot);
104
+ const versions = allDirs.filter(
105
+ (e) => /^\d+\.\d+\.\d+$/.test(e) || /^v\d+$/.test(e)
126
106
  );
107
+ if (versions.length === 0) {
108
+ throw new Error(
109
+ `No version directories found for policy: ${policyId}`
110
+ );
111
+ }
112
+ const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
113
+ versions.sort((a, b) => {
114
+ const [aMaj, aMin = 0, aPatch = 0] = parse(a);
115
+ const [bMaj, bMin = 0, bPatch = 0] = parse(b);
116
+ return aMaj !== bMaj ? aMaj - bMaj : aMin !== bMin ? aMin - bMin : aPatch - bPatch;
117
+ });
118
+ const latestVersion = versions[versions.length - 1];
119
+ let nextVersion;
120
+ if (/^\d+\.\d+\.\d+$/.test(latestVersion)) {
121
+ const [maj, min, patch] = latestVersion.split(".").map(Number);
122
+ nextVersion = `${maj}.${min}.${patch + 1}`;
123
+ } else {
124
+ const latestNumber = Number(latestVersion.replace("v", ""));
125
+ nextVersion = `v${latestNumber + 1}`;
126
+ }
127
+ const latestDirectory = path3.join(policyRoot, latestVersion);
128
+ const nextDirectory = path3.join(policyRoot, nextVersion);
129
+ fs2.cpSync(latestDirectory, nextDirectory, { recursive: true });
130
+ const policyFile = path3.join(nextDirectory, "policy.json");
127
131
  const content = JSON.parse(
128
- fs2.readFileSync(
129
- policyFile,
130
- "utf8"
131
- )
132
+ fs2.readFileSync(policyFile, "utf8")
132
133
  );
133
- content.version = nextVersion;
134
+ if ("policyVersion" in content) {
135
+ content.policyVersion = nextVersion;
136
+ } else {
137
+ content.version = nextVersion;
138
+ }
134
139
  fs2.writeFileSync(
135
140
  policyFile,
136
- JSON.stringify(
137
- content,
138
- null,
139
- 2
140
- ),
141
+ JSON.stringify(content, null, 2),
141
142
  "utf8"
142
143
  );
143
144
  return nextDirectory;
@@ -317,28 +318,34 @@ function evaluateSchemaV1(policy, signals) {
317
318
  };
318
319
  }
319
320
  }
320
- throw new Error(
321
- "[SYS-006] No rule matched \u2014 policy must cover all cases"
322
- );
321
+ return {
322
+ status: "decided",
323
+ outcome: {
324
+ action: "reject",
325
+ requires_override: false,
326
+ reason: "[SYS-006] No rule matched \u2014 default reject. Add a catch-all rule to make this explicit."
327
+ },
328
+ rule_id: "default",
329
+ source: "rule_match"
330
+ };
323
331
  }
324
332
 
325
333
  // src/schema/load-schema-runtime.ts
334
+ var SUPPORTED_SCHEMA_VERSIONS = {
335
+ "1.0.0": {
336
+ semantics: schemaV1Semantics,
337
+ operators: schemaV1Operators,
338
+ evaluate: evaluateSchemaV1
339
+ }
340
+ };
326
341
  function loadSchemaRuntime(schemaVersion) {
327
- const major = Number(
328
- schemaVersion.split(".")[0]
329
- );
330
- switch (major) {
331
- case 1:
332
- return {
333
- semantics: schemaV1Semantics,
334
- operators: schemaV1Operators,
335
- evaluate: evaluateSchemaV1
336
- };
337
- default:
338
- throw new Error(
339
- `Unsupported schema version: ${schemaVersion}`
340
- );
342
+ const runtime = SUPPORTED_SCHEMA_VERSIONS[schemaVersion];
343
+ if (!runtime) {
344
+ throw new Error(
345
+ `Unsupported schema version: ${schemaVersion}. Supported: ${Object.keys(SUPPORTED_SCHEMA_VERSIONS).join(", ")}`
346
+ );
341
347
  }
348
+ return runtime;
342
349
  }
343
350
  export {
344
351
  createPolicy,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/create-policy.ts","../src/generate-bundle.ts","../src/upgrade-policy.ts","../src/validate-policy.ts","../src/define-policy.ts","../src/schema/v1/semantics.ts","../src/schema/v1/operators.ts","../src/schema/v1/evaluator.ts","../src/schema/load-schema-runtime.ts"],"sourcesContent":["import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Scaffolds a new policy directory at `./policies/<policyId>/v1/` and writes\r\n * a skeleton `policy.json` to it.\r\n *\r\n * @param policyId - Unique policy identifier. Must not already exist on disk.\r\n * @returns Absolute path of the created `v1` version directory.\r\n * @throws When `./policies/<policyId>` already exists.\r\n */\r\nexport function createPolicy(\r\n policyId: string\r\n): string {\r\n const policyRoot = path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n const versionDirectory =\r\n path.join(\r\n policyRoot,\r\n \"v1\"\r\n );\r\n\r\n if (fs.existsSync(policyRoot)) {\r\n throw new Error(\r\n `Policy already exists: ${policyId}`\r\n );\r\n }\r\n\r\n fs.mkdirSync(\r\n versionDirectory,\r\n {\r\n recursive: true,\r\n }\r\n );\r\n\r\n fs.writeFileSync(\r\n path.join(\r\n versionDirectory,\r\n \"policy.json\"\r\n ),\r\n\r\n JSON.stringify(\r\n {\r\n policy: policyId,\r\n version: \"v1\",\r\n },\r\n null,\r\n 2\r\n ),\r\n\r\n \"utf8\"\r\n );\r\n\r\n return versionDirectory;\r\n}\r\n\r\n\r\n\r\n\r\n","import * as path from \"node:path\";\r\n\r\nimport {\r\n generateManifest,\r\n writeManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n signManifest,\r\n writeSignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\nimport type {\r\n BundleGenerationResult,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Signer configuration for {@link generateBundle}.\r\n * Provide an explicit private key path — never rely on implicit trust key discovery.\r\n */\r\nexport interface BundleSigner {\r\n /** Absolute or CWD-relative path to the PEM-encoded Ed25519 private key. */\r\n privateKeyPath: string;\r\n}\r\n\r\n/**\r\n * Generates a content-addressed bundle for `policyId`/`policyVersion` in `policyDirectory`:\r\n * 1. Hashes all artifacts and writes `bundle.manifest.json`.\r\n * 2. If `signer` is provided: signs the manifest and writes `bundle.sig`.\r\n * If no signer: produces an unsigned bundle (`bundle.sig` is not written).\r\n *\r\n * Unsigned bundles are valid for development.\r\n * Production deployments should provide a signer.\r\n *\r\n * @param policyId - Policy identifier embedded in the manifest.\r\n * @param policyVersion - Policy version string (e.g. `\"v1\"`).\r\n * @param policyDirectory - Path to the directory containing the policy artifacts.\r\n * @param signer - Optional signing configuration. Omit to produce an unsigned bundle.\r\n * @returns Paths to the written files and the deterministic bundle hash.\r\n */\r\nexport function generateBundle(\r\n policyId: string,\r\n policyVersion: string,\r\n policyDirectory: string,\r\n signer?: BundleSigner\r\n): BundleGenerationResult {\r\n\r\n const directory =\r\n path.resolve(\r\n policyDirectory\r\n );\r\n\r\n const manifest =\r\n generateManifest(\r\n policyId,\r\n policyVersion,\r\n directory\r\n );\r\n\r\n writeManifest(\r\n manifest,\r\n directory\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n directory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (signer) {\r\n const signature =\r\n signManifest(\r\n manifestPath,\r\n signer.privateKeyPath\r\n );\r\n\r\n writeSignature(\r\n signature,\r\n directory\r\n );\r\n }\r\n\r\n return {\r\n success: true,\r\n\r\n manifest_path:\r\n manifestPath,\r\n\r\n signature_path:\r\n signer\r\n ? path.join(directory, \"bundle.sig\")\r\n : null,\r\n\r\n bundle_hash:\r\n manifest.bundle_hash,\r\n };\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\n/**\r\n * Creates the next version directory for `policyId` by copying the latest\r\n * existing version and incrementing its numeric suffix (e.g. `v1` → `v2`).\r\n * The copied `policy.json` has its `version` field updated to the new version\r\n * string.\r\n *\r\n * @param policyId - An existing policy identifier under `./policies/`.\r\n * @returns Absolute path of the newly created version directory.\r\n * @throws When the policy does not exist on disk.\r\n */\r\nexport function upgradePolicy(\r\n policyId: string\r\n): string {\r\n const policyRoot = path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n if (!fs.existsSync(policyRoot)) {\r\n throw new Error(\r\n `Policy does not exist: ${policyId}`\r\n );\r\n }\r\n\r\n const versions = fs\r\n .readdirSync(policyRoot)\r\n .filter((entry) =>\r\n entry.startsWith(\"v\")\r\n )\r\n .sort();\r\n\r\n const latestVersion =\r\n versions[\r\n versions.length - 1\r\n ];\r\n\r\n const latestNumber =\r\n Number(\r\n latestVersion.replace(\"v\", \"\")\r\n );\r\n\r\n const nextVersion =\r\n `v${latestNumber + 1}`;\r\n\r\n const latestDirectory =\r\n path.join(\r\n policyRoot,\r\n latestVersion\r\n );\r\n\r\n const nextDirectory =\r\n path.join(\r\n policyRoot,\r\n nextVersion\r\n );\r\n\r\n fs.cpSync(\r\n latestDirectory,\r\n nextDirectory,\r\n {\r\n recursive: true,\r\n }\r\n );\r\n\r\n const policyFile =\r\n path.join(\r\n nextDirectory,\r\n \"policy.json\"\r\n );\r\n\r\n const content =\r\n JSON.parse(\r\n fs.readFileSync(\r\n policyFile,\r\n \"utf8\"\r\n )\r\n );\r\n\r\n content.version =\r\n nextVersion;\r\n\r\n fs.writeFileSync(\r\n policyFile,\r\n JSON.stringify(\r\n content,\r\n null,\r\n 2\r\n ),\r\n \"utf8\"\r\n );\r\n\r\n return nextDirectory;\r\n}\r\n\r\n\r\n\r\n\r\n","import * as fs from \"node:fs\";\r\nimport * as path from \"node:path\";\r\n\r\nimport {\r\n readManifest,\r\n verifyManifest,\r\n} from \"@parmanasystems/bundle\";\r\n\r\nimport {\r\n readSignature,\r\n verifySignature,\r\n} from \"@parmanasystems/crypto\";\r\n\r\n/**\r\n * Validates every version directory under `./policies/<policyId>` by\r\n * re-verifying all bundle manifests (content hashes) and, when a public key\r\n * path is provided, cryptographic signatures (bundle.sig).\r\n *\r\n * - Version directories without a `bundle.manifest.json` (not yet bundled) are skipped.\r\n * - Version directories without a `bundle.sig` skip signature verification.\r\n * - When `publicKeyPath` is omitted, signature verification is skipped for all versions.\r\n *\r\n * Returns `true` only when every bundled version passes all applicable checks.\r\n *\r\n * @param policyId - Policy identifier whose version directories will be checked.\r\n * @param publicKeyPath - Optional explicit path to the PEM-encoded public key for\r\n * signature verification. When omitted, only manifest content\r\n * hashes are verified.\r\n * @throws When the policy directory does not exist.\r\n */\r\nexport function validatePolicy(\r\n policyId: string,\r\n publicKeyPath?: string\r\n): boolean {\r\n\r\n const policyRoot =\r\n path.join(\r\n \"./policies\",\r\n policyId\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n policyRoot\r\n )\r\n ) {\r\n throw new Error(\r\n `Policy does not exist: ${policyId}`\r\n );\r\n }\r\n\r\n const versions =\r\n fs\r\n .readdirSync(\r\n policyRoot\r\n )\r\n .filter(\r\n (entry) =>\r\n entry.startsWith(\"v\")\r\n )\r\n .sort();\r\n\r\n for (const version of versions) {\r\n\r\n const versionDirectory =\r\n path.join(\r\n policyRoot,\r\n version\r\n );\r\n\r\n const manifestPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.manifest.json\"\r\n );\r\n\r\n if (\r\n !fs.existsSync(\r\n manifestPath\r\n )\r\n ) {\r\n continue;\r\n }\r\n\r\n const manifest =\r\n readManifest(\r\n versionDirectory\r\n );\r\n\r\n const manifestResult =\r\n verifyManifest(\r\n manifest,\r\n versionDirectory\r\n );\r\n\r\n if (\r\n !manifestResult.valid\r\n ) {\r\n return false;\r\n }\r\n\r\n const sigPath =\r\n path.join(\r\n versionDirectory,\r\n \"bundle.sig\"\r\n );\r\n\r\n if (\r\n !publicKeyPath ||\r\n !fs.existsSync(sigPath)\r\n ) {\r\n continue;\r\n }\r\n\r\n const signature =\r\n readSignature(\r\n versionDirectory\r\n );\r\n\r\n const signatureValid =\r\n verifySignature(\r\n manifestPath,\r\n signature,\r\n publicKeyPath\r\n );\r\n\r\n if (\r\n !signatureValid\r\n ) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n\r\n\r\n\r\n","import type {\r\n PolicyDefinition,\r\n PolicyRule,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * Constructs a {@link PolicyDefinition} from a plain config object.\r\n * Use this as the first step in the policy-authoring pipeline before\r\n * serializing the policy to disk and calling {@link generateBundle}.\r\n *\r\n * @param config - Policy id, version, and rules.\r\n */\r\nexport function definePolicy(config: {\r\n id: string;\r\n version: string;\r\n rules: PolicyRule[];\r\n}): PolicyDefinition {\r\n\r\n return {\r\n id: config.id,\r\n\r\n version: config.version,\r\n\r\n rules: config.rules,\r\n };\r\n}\r\n","export const schemaV1Semantics = {\r\n\r\n schemaVersion:\r\n \"1.0.0\",\r\n\r\n ruleConditionField:\r\n \"condition\",\r\n\r\n ruleOutcomeField:\r\n \"outcome\",\r\n\r\n signalReferenceField:\r\n \"signal\",\r\n\r\n supportedOperators: [\r\n \"equals\",\r\n \"greater_than\",\r\n \"less_than\",\r\n ],\r\n};\r\n","export const schemaV1Operators = {\r\n\r\n equals(\r\n left: unknown,\r\n right: unknown\r\n ): boolean {\r\n\r\n return left === right;\r\n },\r\n\r\n greater_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left > right;\r\n },\r\n\r\n less_than(\r\n left: number,\r\n right: number\r\n ): boolean {\r\n\r\n return left < right;\r\n },\r\n};\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./operators.js\";\r\n\r\ninterface BaseCondition {\r\n signal: string;\r\n equals?: unknown;\r\n greater_than?: number;\r\n less_than?: number;\r\n}\r\n\r\ninterface AllCondition {\r\n all: RuleCondition[];\r\n}\r\n\r\ninterface AnyCondition {\r\n any: RuleCondition[];\r\n}\r\n\r\ntype RuleCondition =\r\n | BaseCondition\r\n | AllCondition\r\n | AnyCondition;\r\n\r\ninterface PolicyRule {\r\n id: string;\r\n\r\n condition: RuleCondition;\r\n\r\n outcome: {\r\n action:\r\n | \"approve\"\r\n | \"reject\";\r\n\r\n requires_override:\r\n boolean;\r\n\r\n reason?: string;\r\n };\r\n}\r\n\r\nexport interface SchemaV1Policy {\r\n schemaVersion: string;\r\n\r\n signalsSchema:\r\n Record<string, unknown>;\r\n\r\n rules: PolicyRule[];\r\n}\r\n\r\nfunction evaluateCondition(\r\n condition: RuleCondition,\r\n signals: Record<string, unknown>\r\n): boolean {\r\n\r\n if (\"all\" in condition) {\r\n return condition.all.every(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n if (\"any\" in condition) {\r\n return condition.any.some(\r\n c =>\r\n evaluateCondition(\r\n c,\r\n signals\r\n )\r\n );\r\n }\r\n\r\n const {\r\n signal,\r\n equals,\r\n greater_than,\r\n less_than,\r\n } = condition;\r\n\r\n if (!(signal in signals)) {\r\n\r\n throw new Error(\r\n `Signal not found: ${signal}`\r\n );\r\n }\r\n\r\n const actual =\r\n signals[signal];\r\n\r\n if (equals !== undefined) {\r\n\r\n return schemaV1Operators.equals(\r\n actual,\r\n equals\r\n );\r\n }\r\n\r\n if (\r\n greater_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.greater_than(\r\n actual as number,\r\n greater_than\r\n );\r\n }\r\n\r\n if (\r\n less_than !== undefined\r\n ) {\r\n\r\n return schemaV1Operators.less_than(\r\n actual as number,\r\n less_than\r\n );\r\n }\r\n\r\n return false;\r\n}\r\n\r\nexport function evaluateSchemaV1(\r\n policy: SchemaV1Policy,\r\n signals: Record<string, unknown>\r\n): DecisionResult {\r\n\r\n for (const rule of policy.rules) {\r\n\r\n const matched =\r\n evaluateCondition(\r\n rule.condition,\r\n signals\r\n );\r\n\r\n if (matched) {\r\n\r\n return {\r\n status: \"decided\",\r\n\r\n outcome:\r\n rule.outcome,\r\n\r\n rule_id:\r\n rule.id,\r\n\r\n source:\r\n \"rule_match\",\r\n };\r\n }\r\n }\r\n\r\n throw new Error(\r\n \"[SYS-006] No rule matched — policy must cover all cases\"\r\n );\r\n}\r\n","import type {\r\n DecisionResult\r\n} from \"@parmanasystems/contracts\";\r\n\r\nimport {\r\n evaluateSchemaV1\r\n} from \"./v1/evaluator.js\";\r\n\r\nimport {\r\n schemaV1Operators\r\n} from \"./v1/operators.js\";\r\n\r\nimport {\r\n schemaV1Semantics\r\n} from \"./v1/semantics.js\";\r\n\r\nexport interface SchemaRuntime {\r\n\r\n semantics: unknown;\r\n\r\n operators: unknown;\r\n\r\n evaluate: (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult;\r\n}\r\n\r\nexport function loadSchemaRuntime(\r\n schemaVersion: string\r\n): SchemaRuntime {\r\n\r\n const major =\r\n Number(\r\n schemaVersion.split(\".\")[0]\r\n );\r\n\r\n switch (major) {\r\n\r\n case 1:\r\n\r\n return {\r\n\r\n semantics:\r\n schemaV1Semantics,\r\n\r\n operators:\r\n schemaV1Operators,\r\n\r\n evaluate:\r\n evaluateSchemaV1 as (\r\n policy: unknown,\r\n signals: Record<string, unknown>\r\n ) => DecisionResult,\r\n };\r\n\r\n default:\r\n\r\n throw new Error(\r\n `Unsupported schema version: ${schemaVersion}`\r\n );\r\n }\r\n}\r\n"],"mappings":"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","names":["path","fs","path","fs","path"]}
1
+ {"version":3,"sources":["../src/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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parmanasystems/governance",
3
- "version": "1.71.26",
3
+ "version": "1.71.36",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -18,9 +18,9 @@
18
18
  ],
19
19
  "sideEffects": false,
20
20
  "dependencies": {
21
- "@parmanasystems/bundle": "^1.71.26",
22
- "@parmanasystems/crypto": "^1.71.26",
23
- "@parmanasystems/contracts": "^1.71.26"
21
+ "@parmanasystems/bundle": "^1.71.36",
22
+ "@parmanasystems/crypto": "^1.71.36",
23
+ "@parmanasystems/contracts": "^1.71.36"
24
24
  },
25
25
  "description": "Deterministic governance lifecycle and policy infrastructure for parmanasystems.",
26
26
  "license": "Apache-2.0",