@det-acp/core 0.2.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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +492 -0
  3. package/dist/cli/index.d.ts +15 -0
  4. package/dist/cli/index.d.ts.map +1 -0
  5. package/dist/cli/index.js +308 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/cli/init.d.ts +32 -0
  8. package/dist/cli/init.d.ts.map +1 -0
  9. package/dist/cli/init.js +234 -0
  10. package/dist/cli/init.js.map +1 -0
  11. package/dist/cli/templates.d.ts +27 -0
  12. package/dist/cli/templates.d.ts.map +1 -0
  13. package/dist/cli/templates.js +266 -0
  14. package/dist/cli/templates.js.map +1 -0
  15. package/dist/engine/action-registry.d.ts +49 -0
  16. package/dist/engine/action-registry.d.ts.map +1 -0
  17. package/dist/engine/action-registry.js +95 -0
  18. package/dist/engine/action-registry.js.map +1 -0
  19. package/dist/engine/gate.d.ts +57 -0
  20. package/dist/engine/gate.d.ts.map +1 -0
  21. package/dist/engine/gate.js +145 -0
  22. package/dist/engine/gate.js.map +1 -0
  23. package/dist/engine/runtime.d.ts +98 -0
  24. package/dist/engine/runtime.d.ts.map +1 -0
  25. package/dist/engine/runtime.js +138 -0
  26. package/dist/engine/runtime.js.map +1 -0
  27. package/dist/engine/session.d.ts +74 -0
  28. package/dist/engine/session.d.ts.map +1 -0
  29. package/dist/engine/session.js +343 -0
  30. package/dist/engine/session.js.map +1 -0
  31. package/dist/index.d.ts +48 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +56 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/ledger/ledger.d.ts +58 -0
  36. package/dist/ledger/ledger.d.ts.map +1 -0
  37. package/dist/ledger/ledger.js +188 -0
  38. package/dist/ledger/ledger.js.map +1 -0
  39. package/dist/ledger/query.d.ts +29 -0
  40. package/dist/ledger/query.d.ts.map +1 -0
  41. package/dist/ledger/query.js +61 -0
  42. package/dist/ledger/query.js.map +1 -0
  43. package/dist/ledger/types.d.ts +27 -0
  44. package/dist/ledger/types.d.ts.map +1 -0
  45. package/dist/ledger/types.js +5 -0
  46. package/dist/ledger/types.js.map +1 -0
  47. package/dist/policy/evaluator.d.ts +21 -0
  48. package/dist/policy/evaluator.d.ts.map +1 -0
  49. package/dist/policy/evaluator.js +383 -0
  50. package/dist/policy/evaluator.js.map +1 -0
  51. package/dist/policy/loader.d.ts +27 -0
  52. package/dist/policy/loader.d.ts.map +1 -0
  53. package/dist/policy/loader.js +69 -0
  54. package/dist/policy/loader.js.map +1 -0
  55. package/dist/policy/schema.d.ts +168 -0
  56. package/dist/policy/schema.d.ts.map +1 -0
  57. package/dist/policy/schema.js +107 -0
  58. package/dist/policy/schema.js.map +1 -0
  59. package/dist/proxy/mcp-proxy.d.ts +43 -0
  60. package/dist/proxy/mcp-proxy.d.ts.map +1 -0
  61. package/dist/proxy/mcp-proxy.js +240 -0
  62. package/dist/proxy/mcp-proxy.js.map +1 -0
  63. package/dist/proxy/mcp-types.d.ts +79 -0
  64. package/dist/proxy/mcp-types.d.ts.map +1 -0
  65. package/dist/proxy/mcp-types.js +28 -0
  66. package/dist/proxy/mcp-types.js.map +1 -0
  67. package/dist/proxy/shell-proxy.d.ts +52 -0
  68. package/dist/proxy/shell-proxy.d.ts.map +1 -0
  69. package/dist/proxy/shell-proxy.js +92 -0
  70. package/dist/proxy/shell-proxy.js.map +1 -0
  71. package/dist/rollback/manager.d.ts +62 -0
  72. package/dist/rollback/manager.d.ts.map +1 -0
  73. package/dist/rollback/manager.js +151 -0
  74. package/dist/rollback/manager.js.map +1 -0
  75. package/dist/server/server.d.ts +24 -0
  76. package/dist/server/server.d.ts.map +1 -0
  77. package/dist/server/server.js +200 -0
  78. package/dist/server/server.js.map +1 -0
  79. package/dist/tools/base.d.ts +58 -0
  80. package/dist/tools/base.d.ts.map +1 -0
  81. package/dist/tools/base.js +48 -0
  82. package/dist/tools/base.js.map +1 -0
  83. package/dist/tools/command-run.d.ts +30 -0
  84. package/dist/tools/command-run.d.ts.map +1 -0
  85. package/dist/tools/command-run.js +87 -0
  86. package/dist/tools/command-run.js.map +1 -0
  87. package/dist/tools/file-read.d.ts +34 -0
  88. package/dist/tools/file-read.d.ts.map +1 -0
  89. package/dist/tools/file-read.js +67 -0
  90. package/dist/tools/file-read.js.map +1 -0
  91. package/dist/tools/file-write.d.ts +39 -0
  92. package/dist/tools/file-write.d.ts.map +1 -0
  93. package/dist/tools/file-write.js +158 -0
  94. package/dist/tools/file-write.js.map +1 -0
  95. package/dist/tools/git.d.ts +48 -0
  96. package/dist/tools/git.d.ts.map +1 -0
  97. package/dist/tools/git.js +193 -0
  98. package/dist/tools/git.js.map +1 -0
  99. package/dist/tools/http-request.d.ts +48 -0
  100. package/dist/tools/http-request.d.ts.map +1 -0
  101. package/dist/tools/http-request.js +91 -0
  102. package/dist/tools/http-request.js.map +1 -0
  103. package/dist/types.d.ts +257 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +8 -0
  106. package/dist/types.js.map +1 -0
  107. package/examples/coding-agent.policy.yaml +80 -0
  108. package/examples/devops-deploy.policy.yaml +107 -0
  109. package/examples/mcp-proxy.config.yaml +34 -0
  110. package/examples/simple-session.ts +161 -0
  111. package/examples/video-upscaler.policy.yaml +86 -0
  112. package/package.json +92 -0
  113. package/schemas/generate.ts +18 -0
  114. package/schemas/policy.schema.json +7 -0
@@ -0,0 +1,383 @@
1
+ /**
2
+ * Policy Evaluator — runtime enforcement of policy rules.
3
+ *
4
+ * Given an ActionRequest and a loaded Policy, determines:
5
+ * - allow: action is permitted
6
+ * - deny: action is blocked
7
+ * - gate: action requires approval before execution
8
+ *
9
+ * Supports both stateless (single action) and stateful (session-aware) evaluation.
10
+ */
11
+ import { minimatch } from 'minimatch';
12
+ // ---------------------------------------------------------------------------
13
+ // Main evaluation entry point (stateless — single action)
14
+ // ---------------------------------------------------------------------------
15
+ export function evaluateAction(request, policy, budget) {
16
+ // 1. Check forbidden patterns
17
+ const forbiddenCheck = checkForbiddenPatterns(request, policy);
18
+ if (forbiddenCheck) {
19
+ return {
20
+ verdict: 'deny',
21
+ tool: request.tool,
22
+ reasons: [forbiddenCheck],
23
+ };
24
+ }
25
+ // 2. Check capability exists for this tool
26
+ const capability = findCapability(request.tool, policy);
27
+ if (!capability) {
28
+ return {
29
+ verdict: 'deny',
30
+ tool: request.tool,
31
+ reasons: [`No capability defined for tool "${request.tool}"`],
32
+ };
33
+ }
34
+ // 3. Check scope constraints
35
+ const scopeViolations = checkScope(request, capability);
36
+ if (scopeViolations.length > 0) {
37
+ return {
38
+ verdict: 'deny',
39
+ tool: request.tool,
40
+ reasons: scopeViolations,
41
+ };
42
+ }
43
+ // 4. Check budget limits
44
+ if (budget) {
45
+ const budgetViolations = checkBudget(policy.limits, budget);
46
+ if (budgetViolations.length > 0) {
47
+ return {
48
+ verdict: 'deny',
49
+ tool: request.tool,
50
+ reasons: budgetViolations,
51
+ };
52
+ }
53
+ }
54
+ // 5. Check if a gate applies
55
+ const gate = findGate(request, policy);
56
+ if (gate) {
57
+ return {
58
+ verdict: 'gate',
59
+ tool: request.tool,
60
+ reasons: [`Gate required: ${gate.approval} approval for "${gate.action}" (risk: ${gate.risk_level ?? 'unspecified'})`],
61
+ gate,
62
+ };
63
+ }
64
+ return {
65
+ verdict: 'allow',
66
+ tool: request.tool,
67
+ reasons: ['Action permitted by policy'],
68
+ };
69
+ }
70
+ // ---------------------------------------------------------------------------
71
+ // Session-aware evaluation (stateful)
72
+ // ---------------------------------------------------------------------------
73
+ /**
74
+ * Evaluate an action in the context of an active session.
75
+ * Checks session-level constraints on top of the standard policy checks.
76
+ */
77
+ export function evaluateSessionAction(request, policy, session) {
78
+ const warnings = [];
79
+ // 1. Check if session is still active
80
+ if (session.state !== 'active') {
81
+ return {
82
+ verdict: 'deny',
83
+ tool: request.tool,
84
+ reasons: [`Session is ${session.state}, not accepting new actions`],
85
+ };
86
+ }
87
+ // 2. Check session constraints before standard policy checks
88
+ const sessionConstraints = policy.session;
89
+ if (sessionConstraints) {
90
+ // Max actions per session
91
+ if (sessionConstraints.max_actions != null) {
92
+ if (session.budget.actionsEvaluated >= sessionConstraints.max_actions) {
93
+ return {
94
+ verdict: 'deny',
95
+ tool: request.tool,
96
+ reasons: [`Session action limit reached: ${session.budget.actionsEvaluated} >= ${sessionConstraints.max_actions}`],
97
+ };
98
+ }
99
+ // Warn when approaching limit
100
+ const remaining = sessionConstraints.max_actions - session.budget.actionsEvaluated;
101
+ if (remaining <= 5) {
102
+ warnings.push(`Approaching action limit: ${remaining} actions remaining`);
103
+ }
104
+ }
105
+ // Max denials — terminate session if too many denials
106
+ if (sessionConstraints.max_denials != null) {
107
+ if (session.budget.actionsDenied >= sessionConstraints.max_denials) {
108
+ return {
109
+ verdict: 'deny',
110
+ tool: request.tool,
111
+ reasons: [`Session denial limit reached: ${session.budget.actionsDenied} >= ${sessionConstraints.max_denials}. Session should be terminated.`],
112
+ };
113
+ }
114
+ }
115
+ // Rate limiting
116
+ if (sessionConstraints.rate_limit) {
117
+ const rateLimitViolation = checkRateLimit(session, sessionConstraints.rate_limit.max_per_minute);
118
+ if (rateLimitViolation) {
119
+ return {
120
+ verdict: 'deny',
121
+ tool: request.tool,
122
+ reasons: [rateLimitViolation],
123
+ };
124
+ }
125
+ }
126
+ // Escalation rules
127
+ if (sessionConstraints.escalation) {
128
+ const escalation = checkEscalation(session, sessionConstraints.escalation);
129
+ if (escalation) {
130
+ return {
131
+ verdict: 'gate',
132
+ tool: request.tool,
133
+ reasons: [escalation.reason],
134
+ gate: {
135
+ action: request.tool,
136
+ approval: 'human',
137
+ risk_level: 'medium',
138
+ condition: escalation.trigger,
139
+ },
140
+ warnings,
141
+ };
142
+ }
143
+ }
144
+ }
145
+ // 3. Run standard policy checks (with session budget)
146
+ const result = evaluateAction(request, policy, session.budget);
147
+ // Attach warnings
148
+ if (warnings.length > 0) {
149
+ return { ...result, warnings };
150
+ }
151
+ return result;
152
+ }
153
+ // ---------------------------------------------------------------------------
154
+ // Rate limiting
155
+ // ---------------------------------------------------------------------------
156
+ function checkRateLimit(session, maxPerMinute) {
157
+ const now = Date.now();
158
+ const oneMinuteAgo = now - 60_000;
159
+ // Count actions in the last minute
160
+ const recentActions = session.actions.filter((a) => {
161
+ const actionTime = new Date(a.timestamp).getTime();
162
+ return actionTime >= oneMinuteAgo;
163
+ });
164
+ if (recentActions.length >= maxPerMinute) {
165
+ return `Rate limit exceeded: ${recentActions.length} actions in the last minute (limit: ${maxPerMinute})`;
166
+ }
167
+ return null;
168
+ }
169
+ function checkEscalation(session, rules) {
170
+ const elapsedMinutes = (Date.now() - session.budget.startedAt) / 60_000;
171
+ for (const rule of rules) {
172
+ if (rule.after_actions != null && session.budget.actionsEvaluated >= rule.after_actions) {
173
+ // Check if a human check-in has already been done after this threshold
174
+ // by looking for a recent gate approval in the session history
175
+ const lastCheckinIndex = findLastCheckin(session, rule.after_actions);
176
+ if (lastCheckinIndex === -1) {
177
+ return {
178
+ reason: `Escalation: ${session.budget.actionsEvaluated} actions evaluated, human check-in required after ${rule.after_actions}`,
179
+ trigger: `after_actions:${rule.after_actions}`,
180
+ };
181
+ }
182
+ }
183
+ if (rule.after_minutes != null && elapsedMinutes >= rule.after_minutes) {
184
+ const lastTimeCheckin = findLastTimeCheckin(session, rule.after_minutes);
185
+ if (lastTimeCheckin === -1) {
186
+ return {
187
+ reason: `Escalation: ${Math.floor(elapsedMinutes)} minutes elapsed, human check-in required after ${rule.after_minutes} minutes`,
188
+ trigger: `after_minutes:${rule.after_minutes}`,
189
+ };
190
+ }
191
+ }
192
+ }
193
+ return null;
194
+ }
195
+ /**
196
+ * Find the last action index where a human check-in gate was approved
197
+ * after the given threshold was crossed.
198
+ */
199
+ function findLastCheckin(session, threshold) {
200
+ // Look for any gated action (with human approval) that was resolved
201
+ // after the threshold was reached
202
+ for (let i = session.actions.length - 1; i >= 0; i--) {
203
+ const action = session.actions[i];
204
+ if (action.index >= threshold &&
205
+ action.validation.verdict === 'gate' &&
206
+ action.result !== undefined) {
207
+ return i;
208
+ }
209
+ }
210
+ return -1;
211
+ }
212
+ function findLastTimeCheckin(session, _afterMinutes) {
213
+ // Look for any gated action that was a time-based escalation and was resolved
214
+ for (let i = session.actions.length - 1; i >= 0; i--) {
215
+ const action = session.actions[i];
216
+ if (action.validation.verdict === 'gate' &&
217
+ action.validation.gate?.condition?.startsWith('after_minutes:') &&
218
+ action.result !== undefined) {
219
+ return i;
220
+ }
221
+ }
222
+ return -1;
223
+ }
224
+ // ---------------------------------------------------------------------------
225
+ // Forbidden pattern checks
226
+ // ---------------------------------------------------------------------------
227
+ function checkForbiddenPatterns(request, policy) {
228
+ const input = request.input;
229
+ for (const forbidden of policy.forbidden) {
230
+ const pattern = forbidden.pattern;
231
+ // Check against path-like inputs
232
+ const pathValue = (input.path ?? input.file ?? input.target);
233
+ if (pathValue && minimatch(pathValue, pattern)) {
234
+ return `Path "${pathValue}" matches forbidden pattern "${pattern}"`;
235
+ }
236
+ // Check against command inputs
237
+ const command = (input.command ?? input.cmd);
238
+ if (command && command.includes(pattern)) {
239
+ return `Command contains forbidden pattern "${pattern}"`;
240
+ }
241
+ // Check against URL inputs
242
+ const url = (input.url ?? input.endpoint);
243
+ if (url && minimatch(url, pattern)) {
244
+ return `URL "${url}" matches forbidden pattern "${pattern}"`;
245
+ }
246
+ }
247
+ return null;
248
+ }
249
+ // ---------------------------------------------------------------------------
250
+ // Capability lookup
251
+ // ---------------------------------------------------------------------------
252
+ function findCapability(tool, policy) {
253
+ return policy.capabilities.find((cap) => cap.tool === tool);
254
+ }
255
+ // ---------------------------------------------------------------------------
256
+ // Scope validation
257
+ // ---------------------------------------------------------------------------
258
+ function checkScope(request, capability) {
259
+ const violations = [];
260
+ const input = request.input;
261
+ const scope = capability.scope;
262
+ // Path scope
263
+ if (scope.paths) {
264
+ const pathValue = (input.path ?? input.file ?? input.target);
265
+ if (pathValue) {
266
+ const allowed = scope.paths.some((pattern) => minimatch(pathValue, pattern));
267
+ if (!allowed) {
268
+ violations.push(`Path "${pathValue}" is outside allowed scope: [${scope.paths.join(', ')}]`);
269
+ }
270
+ }
271
+ }
272
+ // Binary scope (for command:run)
273
+ if (scope.binaries) {
274
+ const binary = (input.binary ?? input.command);
275
+ if (binary) {
276
+ // Extract the base binary name (first word of the command)
277
+ const baseBinary = binary.split(/\s+/)[0];
278
+ const baseName = baseBinary.split('/').pop() ?? baseBinary;
279
+ if (!scope.binaries.includes(baseName)) {
280
+ violations.push(`Binary "${baseName}" is not in allowed list: [${scope.binaries.join(', ')}]`);
281
+ }
282
+ }
283
+ }
284
+ // Domain scope (for http:request)
285
+ if (scope.domains) {
286
+ const url = (input.url ?? input.endpoint);
287
+ if (url) {
288
+ try {
289
+ const parsed = new URL(url);
290
+ if (!scope.domains.includes(parsed.hostname)) {
291
+ violations.push(`Domain "${parsed.hostname}" is not in allowed list: [${scope.domains.join(', ')}]`);
292
+ }
293
+ }
294
+ catch {
295
+ violations.push(`Invalid URL: "${url}"`);
296
+ }
297
+ }
298
+ }
299
+ // Method scope (for http:request)
300
+ if (scope.methods) {
301
+ const method = (input.method ?? 'GET').toUpperCase();
302
+ if (!scope.methods.includes(method)) {
303
+ violations.push(`HTTP method "${method}" is not in allowed list: [${scope.methods.join(', ')}]`);
304
+ }
305
+ }
306
+ // Repo scope (for git operations)
307
+ if (scope.repos) {
308
+ const repo = (input.repo ?? input.repository);
309
+ if (repo) {
310
+ const allowed = scope.repos.some((pattern) => minimatch(repo, pattern));
311
+ if (!allowed) {
312
+ violations.push(`Repository "${repo}" is outside allowed scope: [${scope.repos.join(', ')}]`);
313
+ }
314
+ }
315
+ }
316
+ return violations;
317
+ }
318
+ // ---------------------------------------------------------------------------
319
+ // Budget checks
320
+ // ---------------------------------------------------------------------------
321
+ function checkBudget(limits, budget) {
322
+ const violations = [];
323
+ if (limits.max_runtime_ms != null) {
324
+ const elapsed = Date.now() - budget.startedAt;
325
+ if (elapsed > limits.max_runtime_ms) {
326
+ violations.push(`Runtime budget exceeded: ${elapsed}ms > ${limits.max_runtime_ms}ms`);
327
+ }
328
+ }
329
+ if (limits.max_files_changed != null && budget.filesChanged >= limits.max_files_changed) {
330
+ violations.push(`File change budget exceeded: ${budget.filesChanged} >= ${limits.max_files_changed}`);
331
+ }
332
+ if (limits.max_output_bytes != null && budget.totalOutputBytes >= limits.max_output_bytes) {
333
+ violations.push(`Output size budget exceeded: ${budget.totalOutputBytes} >= ${limits.max_output_bytes}`);
334
+ }
335
+ if (limits.max_retries != null && budget.retries >= limits.max_retries) {
336
+ violations.push(`Retry budget exceeded: ${budget.retries} >= ${limits.max_retries}`);
337
+ }
338
+ if (limits.max_cost_usd != null && budget.costUsd >= limits.max_cost_usd) {
339
+ violations.push(`Cost budget exceeded: $${budget.costUsd} >= $${limits.max_cost_usd}`);
340
+ }
341
+ return violations;
342
+ }
343
+ // ---------------------------------------------------------------------------
344
+ // Gate lookup
345
+ // ---------------------------------------------------------------------------
346
+ function findGate(request, policy) {
347
+ return policy.gates.find((gate) => {
348
+ if (gate.action !== request.tool)
349
+ return false;
350
+ // If gate has a condition, evaluate it
351
+ if (gate.condition === 'outside_scope') {
352
+ // This gate fires only if the action targets something outside scope
353
+ const capability = findCapability(request.tool, policy);
354
+ if (capability) {
355
+ const scopeViolations = checkScope(request, capability);
356
+ return scopeViolations.length > 0;
357
+ }
358
+ }
359
+ // No condition or unknown condition — gate always applies
360
+ return !gate.condition;
361
+ });
362
+ }
363
+ // ---------------------------------------------------------------------------
364
+ // Utility: assess risk level for an action
365
+ // ---------------------------------------------------------------------------
366
+ export function assessRiskLevel(request, policy) {
367
+ // Check if there's an explicit gate with a risk level
368
+ const gate = policy.gates.find((g) => g.action === request.tool);
369
+ if (gate?.risk_level)
370
+ return gate.risk_level;
371
+ // Heuristic risk assessment
372
+ const tool = request.tool;
373
+ if (tool === 'file:delete' || tool === 'command:run')
374
+ return 'high';
375
+ if (tool === 'file:write' || tool === 'git:apply')
376
+ return 'medium';
377
+ if (tool === 'http:request')
378
+ return 'medium';
379
+ if (tool === 'file:read' || tool === 'git:diff')
380
+ return 'low';
381
+ return 'medium';
382
+ }
383
+ //# sourceMappingURL=evaluator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../src/policy/evaluator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Policy Loader — reads a YAML policy file and validates it against the Zod schema.
3
+ */
4
+ import type { Policy } from '../types.js';
5
+ export declare class PolicyValidationError extends Error {
6
+ readonly issues: Array<{
7
+ path: string;
8
+ message: string;
9
+ }>;
10
+ constructor(message: string, issues: Array<{
11
+ path: string;
12
+ message: string;
13
+ }>);
14
+ }
15
+ /**
16
+ * Load and validate a policy from a YAML file path.
17
+ */
18
+ export declare function loadPolicyFromFile(filePath: string): Policy;
19
+ /**
20
+ * Parse and validate a policy from a YAML string.
21
+ */
22
+ export declare function parsePolicyYaml(yamlString: string): Policy;
23
+ /**
24
+ * Validate a policy object (already parsed).
25
+ */
26
+ export declare function validatePolicy(policy: unknown): Policy;
27
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/policy/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;gBADhE,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAKnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA8B1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAatD"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Policy Loader — reads a YAML policy file and validates it against the Zod schema.
3
+ */
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import yaml from 'js-yaml';
7
+ import { PolicySchema } from './schema.js';
8
+ export class PolicyValidationError extends Error {
9
+ issues;
10
+ constructor(message, issues) {
11
+ super(message);
12
+ this.issues = issues;
13
+ this.name = 'PolicyValidationError';
14
+ }
15
+ }
16
+ /**
17
+ * Load and validate a policy from a YAML file path.
18
+ */
19
+ export function loadPolicyFromFile(filePath) {
20
+ const absPath = path.resolve(filePath);
21
+ if (!fs.existsSync(absPath)) {
22
+ throw new Error(`Policy file not found: ${absPath}`);
23
+ }
24
+ const raw = fs.readFileSync(absPath, 'utf-8');
25
+ return parsePolicyYaml(raw);
26
+ }
27
+ /**
28
+ * Parse and validate a policy from a YAML string.
29
+ */
30
+ export function parsePolicyYaml(yamlString) {
31
+ let parsed;
32
+ try {
33
+ parsed = yaml.load(yamlString);
34
+ }
35
+ catch (err) {
36
+ throw new PolicyValidationError('Invalid YAML syntax', [
37
+ { path: '', message: err.message },
38
+ ]);
39
+ }
40
+ if (parsed === null || parsed === undefined || typeof parsed !== 'object') {
41
+ throw new PolicyValidationError('Policy must be a YAML object', [
42
+ { path: '', message: 'Expected an object, got ' + typeof parsed },
43
+ ]);
44
+ }
45
+ const result = PolicySchema.safeParse(parsed);
46
+ if (!result.success) {
47
+ const issues = result.error.issues.map((issue) => ({
48
+ path: issue.path.join('.'),
49
+ message: issue.message,
50
+ }));
51
+ throw new PolicyValidationError(`Policy validation failed with ${issues.length} issue(s)`, issues);
52
+ }
53
+ return result.data;
54
+ }
55
+ /**
56
+ * Validate a policy object (already parsed).
57
+ */
58
+ export function validatePolicy(policy) {
59
+ const result = PolicySchema.safeParse(policy);
60
+ if (!result.success) {
61
+ const issues = result.error.issues.map((issue) => ({
62
+ path: issue.path.join('.'),
63
+ message: issue.message,
64
+ }));
65
+ throw new PolicyValidationError(`Policy validation failed with ${issues.length} issue(s)`, issues);
66
+ }
67
+ return result.data;
68
+ }
69
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/policy/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAG5B;IAFlB,YACE,OAAe,EACC,MAAgD;QAEhE,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,WAAM,GAAN,MAAM,CAA0C;QAGhE,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,EAAE;YACrD,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAG,GAAa,CAAC,OAAO,EAAE;SAC9C,CAAC,CAAC;IACL,CAAC;IAED,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1E,MAAM,IAAI,qBAAqB,CAAC,8BAA8B,EAAE;YAC9D,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,0BAA0B,GAAG,OAAO,MAAM,EAAE;SAClE,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,qBAAqB,CAC7B,iCAAiC,MAAM,CAAC,MAAM,WAAW,EACzD,MAAM,CACP,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC,IAAc,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAAe;IAC5C,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC,CAAC;QACJ,MAAM,IAAI,qBAAqB,CAC7B,iCAAiC,MAAM,CAAC,MAAM,WAAW,EACzD,MAAM,CACP,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,IAAc,CAAC;AAC/B,CAAC"}