@provos/ironcurtain 0.1.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 (160) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +311 -0
  3. package/dist/agent/index.d.ts +10 -0
  4. package/dist/agent/index.js +71 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/agent/prompts.d.ts +5 -0
  7. package/dist/agent/prompts.js +26 -0
  8. package/dist/agent/prompts.js.map +1 -0
  9. package/dist/agent/tools.d.ts +13 -0
  10. package/dist/agent/tools.js +51 -0
  11. package/dist/agent/tools.js.map +1 -0
  12. package/dist/cli.d.ts +2 -0
  13. package/dist/cli.js +78 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config/constitution.md +16 -0
  16. package/dist/config/generated/compiled-policy.json +236 -0
  17. package/dist/config/generated/test-scenarios.json +765 -0
  18. package/dist/config/generated/tool-annotations.json +955 -0
  19. package/dist/config/index.d.ts +25 -0
  20. package/dist/config/index.js +151 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/config/mcp-servers.json +22 -0
  23. package/dist/config/model-provider.d.ts +49 -0
  24. package/dist/config/model-provider.js +78 -0
  25. package/dist/config/model-provider.js.map +1 -0
  26. package/dist/config/paths.d.ts +59 -0
  27. package/dist/config/paths.js +96 -0
  28. package/dist/config/paths.js.map +1 -0
  29. package/dist/config/types.d.ts +89 -0
  30. package/dist/config/types.js +2 -0
  31. package/dist/config/types.js.map +1 -0
  32. package/dist/config/user-config.d.ts +93 -0
  33. package/dist/config/user-config.js +309 -0
  34. package/dist/config/user-config.js.map +1 -0
  35. package/dist/hash.d.ts +17 -0
  36. package/dist/hash.js +34 -0
  37. package/dist/hash.js.map +1 -0
  38. package/dist/index.d.ts +1 -0
  39. package/dist/index.js +61 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/logger.d.ts +11 -0
  42. package/dist/logger.js +93 -0
  43. package/dist/logger.js.map +1 -0
  44. package/dist/pipeline/annotate.d.ts +9 -0
  45. package/dist/pipeline/annotate.js +136 -0
  46. package/dist/pipeline/annotate.js.map +1 -0
  47. package/dist/pipeline/compile.d.ts +23 -0
  48. package/dist/pipeline/compile.js +386 -0
  49. package/dist/pipeline/compile.js.map +1 -0
  50. package/dist/pipeline/constitution-compiler.d.ts +22 -0
  51. package/dist/pipeline/constitution-compiler.js +197 -0
  52. package/dist/pipeline/constitution-compiler.js.map +1 -0
  53. package/dist/pipeline/generate-with-repair.d.ts +22 -0
  54. package/dist/pipeline/generate-with-repair.js +64 -0
  55. package/dist/pipeline/generate-with-repair.js.map +1 -0
  56. package/dist/pipeline/handwritten-scenarios.d.ts +9 -0
  57. package/dist/pipeline/handwritten-scenarios.js +321 -0
  58. package/dist/pipeline/handwritten-scenarios.js.map +1 -0
  59. package/dist/pipeline/llm-logger.d.ts +42 -0
  60. package/dist/pipeline/llm-logger.js +78 -0
  61. package/dist/pipeline/llm-logger.js.map +1 -0
  62. package/dist/pipeline/pipeline-shared.d.ts +47 -0
  63. package/dist/pipeline/pipeline-shared.js +145 -0
  64. package/dist/pipeline/pipeline-shared.js.map +1 -0
  65. package/dist/pipeline/policy-verifier.d.ts +46 -0
  66. package/dist/pipeline/policy-verifier.js +277 -0
  67. package/dist/pipeline/policy-verifier.js.map +1 -0
  68. package/dist/pipeline/scenario-generator.d.ts +11 -0
  69. package/dist/pipeline/scenario-generator.js +128 -0
  70. package/dist/pipeline/scenario-generator.js.map +1 -0
  71. package/dist/pipeline/tool-annotator.d.ts +24 -0
  72. package/dist/pipeline/tool-annotator.js +201 -0
  73. package/dist/pipeline/tool-annotator.js.map +1 -0
  74. package/dist/pipeline/types.d.ts +122 -0
  75. package/dist/pipeline/types.js +10 -0
  76. package/dist/pipeline/types.js.map +1 -0
  77. package/dist/sandbox/index.d.ts +39 -0
  78. package/dist/sandbox/index.js +178 -0
  79. package/dist/sandbox/index.js.map +1 -0
  80. package/dist/session/agent-session.d.ts +83 -0
  81. package/dist/session/agent-session.js +382 -0
  82. package/dist/session/agent-session.js.map +1 -0
  83. package/dist/session/cli-transport.d.ts +61 -0
  84. package/dist/session/cli-transport.js +320 -0
  85. package/dist/session/cli-transport.js.map +1 -0
  86. package/dist/session/errors.d.ts +19 -0
  87. package/dist/session/errors.js +33 -0
  88. package/dist/session/errors.js.map +1 -0
  89. package/dist/session/index.d.ts +29 -0
  90. package/dist/session/index.js +104 -0
  91. package/dist/session/index.js.map +1 -0
  92. package/dist/session/message-compactor.d.ts +32 -0
  93. package/dist/session/message-compactor.js +81 -0
  94. package/dist/session/message-compactor.js.map +1 -0
  95. package/dist/session/prompts.d.ts +5 -0
  96. package/dist/session/prompts.js +62 -0
  97. package/dist/session/prompts.js.map +1 -0
  98. package/dist/session/resource-budget-tracker.d.ts +124 -0
  99. package/dist/session/resource-budget-tracker.js +327 -0
  100. package/dist/session/resource-budget-tracker.js.map +1 -0
  101. package/dist/session/step-loop-detector.d.ts +63 -0
  102. package/dist/session/step-loop-detector.js +136 -0
  103. package/dist/session/step-loop-detector.js.map +1 -0
  104. package/dist/session/transport.d.ts +24 -0
  105. package/dist/session/transport.js +2 -0
  106. package/dist/session/transport.js.map +1 -0
  107. package/dist/session/truncate-result.d.ts +35 -0
  108. package/dist/session/truncate-result.js +71 -0
  109. package/dist/session/truncate-result.js.map +1 -0
  110. package/dist/session/types.d.ts +220 -0
  111. package/dist/session/types.js +6 -0
  112. package/dist/session/types.js.map +1 -0
  113. package/dist/trusted-process/audit-log.d.ts +7 -0
  114. package/dist/trusted-process/audit-log.js +21 -0
  115. package/dist/trusted-process/audit-log.js.map +1 -0
  116. package/dist/trusted-process/call-circuit-breaker.d.ts +33 -0
  117. package/dist/trusted-process/call-circuit-breaker.js +61 -0
  118. package/dist/trusted-process/call-circuit-breaker.js.map +1 -0
  119. package/dist/trusted-process/escalation.d.ts +7 -0
  120. package/dist/trusted-process/escalation.js +38 -0
  121. package/dist/trusted-process/escalation.js.map +1 -0
  122. package/dist/trusted-process/index.d.ts +32 -0
  123. package/dist/trusted-process/index.js +151 -0
  124. package/dist/trusted-process/index.js.map +1 -0
  125. package/dist/trusted-process/mcp-client-manager.d.ts +25 -0
  126. package/dist/trusted-process/mcp-client-manager.js +90 -0
  127. package/dist/trusted-process/mcp-client-manager.js.map +1 -0
  128. package/dist/trusted-process/mcp-proxy-server.d.ts +24 -0
  129. package/dist/trusted-process/mcp-proxy-server.js +451 -0
  130. package/dist/trusted-process/mcp-proxy-server.js.map +1 -0
  131. package/dist/trusted-process/path-utils.d.ts +50 -0
  132. package/dist/trusted-process/path-utils.js +158 -0
  133. package/dist/trusted-process/path-utils.js.map +1 -0
  134. package/dist/trusted-process/policy-engine.d.ts +88 -0
  135. package/dist/trusted-process/policy-engine.js +523 -0
  136. package/dist/trusted-process/policy-engine.js.map +1 -0
  137. package/dist/trusted-process/policy-roots.d.ts +50 -0
  138. package/dist/trusted-process/policy-roots.js +67 -0
  139. package/dist/trusted-process/policy-roots.js.map +1 -0
  140. package/dist/trusted-process/policy-types.d.ts +6 -0
  141. package/dist/trusted-process/policy-types.js +2 -0
  142. package/dist/trusted-process/policy-types.js.map +1 -0
  143. package/dist/trusted-process/sandbox-integration.d.ts +92 -0
  144. package/dist/trusted-process/sandbox-integration.js +184 -0
  145. package/dist/trusted-process/sandbox-integration.js.map +1 -0
  146. package/dist/types/argument-roles.d.ts +112 -0
  147. package/dist/types/argument-roles.js +344 -0
  148. package/dist/types/argument-roles.js.map +1 -0
  149. package/dist/types/audit.d.ts +18 -0
  150. package/dist/types/audit.js +2 -0
  151. package/dist/types/audit.js.map +1 -0
  152. package/dist/types/mcp.d.ts +20 -0
  153. package/dist/types/mcp.js +2 -0
  154. package/dist/types/mcp.js.map +1 -0
  155. package/package.json +83 -0
  156. package/src/config/constitution.md +16 -0
  157. package/src/config/generated/compiled-policy.json +236 -0
  158. package/src/config/generated/test-scenarios.json +765 -0
  159. package/src/config/generated/tool-annotations.json +955 -0
  160. package/src/config/mcp-servers.json +22 -0
@@ -0,0 +1,523 @@
1
+ /**
2
+ * PolicyEngine -- Two-phase declarative policy evaluation.
3
+ *
4
+ * Phase 1: Hardcoded structural invariants (protected paths, unknown tools).
5
+ * These are never overridden by compiled rules. Sandbox containment
6
+ * is checked per-role: roles whose paths are all within the sandbox
7
+ * are resolved here and skipped in Phase 2.
8
+ *
9
+ * Phase 2: Compiled declarative rules loaded from compiled-policy.json.
10
+ * Each distinct role from the tool's annotation is evaluated
11
+ * independently through the rule chain (first-match-wins per role).
12
+ * The most restrictive result wins: deny > escalate > allow.
13
+ * Roles already resolved by Phase 1 sandbox containment are skipped.
14
+ */
15
+ import { getPathRoles, getUrlRoles, getRoleDefinition, resolveRealPath, SANDBOX_SAFE_PATH_ROLES, } from '../types/argument-roles.js';
16
+ /**
17
+ * Heuristically extracts filesystem paths from tool call arguments.
18
+ * Any string value starting with '/', '.', or '~' is treated as a path.
19
+ * Handles both single string values and arrays of strings.
20
+ */
21
+ function extractPathsHeuristic(args) {
22
+ const paths = [];
23
+ for (const value of Object.values(args)) {
24
+ if (typeof value === 'string' && (value.startsWith('/') || value.startsWith('.') || value.startsWith('~'))) {
25
+ paths.push(value);
26
+ }
27
+ else if (Array.isArray(value)) {
28
+ for (const item of value) {
29
+ if (typeof item === 'string' && (item.startsWith('/') || item.startsWith('.') || item.startsWith('~'))) {
30
+ paths.push(item);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ return paths;
36
+ }
37
+ /**
38
+ * Extracts paths from arguments based on annotation roles.
39
+ * Only returns paths for arguments whose annotated roles intersect
40
+ * with the target roles. Handles both string and string[] arguments.
41
+ */
42
+ function extractAnnotatedPaths(args, annotation, targetRoles) {
43
+ const paths = [];
44
+ for (const [argName, roles] of Object.entries(annotation.args)) {
45
+ if (!roles.some(r => targetRoles.includes(r)))
46
+ continue;
47
+ const value = args[argName];
48
+ if (typeof value === 'string') {
49
+ paths.push(value);
50
+ }
51
+ else if (Array.isArray(value)) {
52
+ for (const item of value) {
53
+ if (typeof item === 'string')
54
+ paths.push(item);
55
+ }
56
+ }
57
+ }
58
+ return paths;
59
+ }
60
+ /**
61
+ * Checks whether a target path is contained within a directory.
62
+ * Both paths are resolved to their real canonical form (following symlinks)
63
+ * before comparison, which neutralizes both path traversal and symlink attacks.
64
+ */
65
+ function isWithinDirectory(targetPath, directory) {
66
+ const resolved = resolveRealPath(targetPath);
67
+ const resolvedDir = resolveRealPath(directory);
68
+ return resolved === resolvedDir || resolved.startsWith(resolvedDir + '/');
69
+ }
70
+ /**
71
+ * Checks whether a resolved path matches any protected path.
72
+ * A path is protected if it equals a protected path exactly
73
+ * or is contained within a protected directory.
74
+ * Both sides are resolved through symlinks for accurate comparison.
75
+ */
76
+ function isProtectedPath(resolvedPath, protectedPaths) {
77
+ const realPath = resolveRealPath(resolvedPath);
78
+ return protectedPaths.some(pp => {
79
+ const resolvedPP = resolveRealPath(pp);
80
+ return realPath === resolvedPP || realPath.startsWith(resolvedPP + '/');
81
+ });
82
+ }
83
+ const NO_ROLES_RESOLVED = new Set();
84
+ /** Wraps a final EvaluationResult into a StructuralResult. */
85
+ function finalDecision(decision) {
86
+ return { decision, sandboxResolvedRoles: NO_ROLES_RESOLVED };
87
+ }
88
+ /** Higher severity = more restrictive. Used to pick the strictest per-role result. */
89
+ const DECISION_SEVERITY = {
90
+ allow: 0,
91
+ escalate: 1,
92
+ deny: 2,
93
+ };
94
+ /**
95
+ * Collects all distinct non-"none" roles from a tool annotation's arguments.
96
+ * Returns an empty array if the tool has no role-bearing arguments.
97
+ */
98
+ function collectDistinctRoles(annotation) {
99
+ const roles = new Set();
100
+ for (const argRoles of Object.values(annotation.args)) {
101
+ for (const role of argRoles) {
102
+ if (getRoleDefinition(role).isResourceIdentifier)
103
+ roles.add(role);
104
+ }
105
+ }
106
+ return [...roles];
107
+ }
108
+ /**
109
+ * Extracts URL values from arguments based on annotation roles.
110
+ * Returns an array of { value, role, roleDef } for each URL-category argument.
111
+ */
112
+ function extractAnnotatedUrls(args, annotation, targetRoles) {
113
+ const urls = [];
114
+ for (const [argName, roles] of Object.entries(annotation.args)) {
115
+ const matchingRole = roles.find(r => targetRoles.includes(r));
116
+ if (!matchingRole)
117
+ continue;
118
+ const value = args[argName];
119
+ const roleDef = getRoleDefinition(matchingRole);
120
+ if (typeof value === 'string') {
121
+ urls.push({ value, role: matchingRole, roleDef });
122
+ }
123
+ else if (Array.isArray(value)) {
124
+ for (const item of value) {
125
+ if (typeof item === 'string') {
126
+ urls.push({ value: item, role: matchingRole, roleDef });
127
+ }
128
+ }
129
+ }
130
+ }
131
+ return urls;
132
+ }
133
+ /**
134
+ * Applies the resolution pipeline for a URL-category value:
135
+ * 1. resolveForPolicy(value, allArgs) -- resolve named remote to URL
136
+ * 2. normalize(resolvedValue) -- canonicalize URL format
137
+ * 3. prepareForPolicy(normalizedValue) -- extract domain for allowlist check
138
+ */
139
+ function resolveUrlForDomainCheck(value, roleDef, allArgs) {
140
+ const resolved = roleDef.resolveForPolicy?.(value, allArgs) ?? value;
141
+ const normalized = roleDef.normalize(resolved);
142
+ return roleDef.prepareForPolicy?.(normalized) ?? normalized;
143
+ }
144
+ /**
145
+ * Checks whether a domain matches any pattern in an allowlist.
146
+ * Supports exact match, `*` wildcard (matches everything),
147
+ * and `*.example.com` prefix wildcards (matches example.com and *.example.com).
148
+ */
149
+ export function domainMatchesAllowlist(domain, allowedDomains) {
150
+ return allowedDomains.some(pattern => {
151
+ if (pattern === '*')
152
+ return true;
153
+ if (pattern.startsWith('*.')) {
154
+ const suffix = pattern.slice(1); // ".github.com"
155
+ return domain === pattern.slice(2) || domain.endsWith(suffix);
156
+ }
157
+ return domain === pattern;
158
+ });
159
+ }
160
+ /**
161
+ * Checks whether a rule has role-related conditions (roles, paths, or domains).
162
+ * Rules without these conditions are role-agnostic and match any role.
163
+ */
164
+ function hasRoleConditions(rule) {
165
+ return rule.if.roles !== undefined || rule.if.paths !== undefined || rule.if.domains !== undefined;
166
+ }
167
+ /**
168
+ * Checks whether a rule's role-related conditions include a specific role.
169
+ * For `roles` conditions: the role must be in the list.
170
+ * For `paths` conditions: the role must be in the paths.roles list.
171
+ * For `domains` conditions: the role must be in the domains.roles list.
172
+ */
173
+ function ruleRelevantToRole(rule, role) {
174
+ const cond = rule.if;
175
+ if (cond.roles !== undefined && !cond.roles.includes(role))
176
+ return false;
177
+ if (cond.paths !== undefined && !cond.paths.roles.includes(role))
178
+ return false;
179
+ if (cond.domains !== undefined && !cond.domains.roles.includes(role))
180
+ return false;
181
+ return true;
182
+ }
183
+ export class PolicyEngine {
184
+ annotationMap;
185
+ compiledPolicy;
186
+ protectedPaths;
187
+ allowedDirectory;
188
+ serverDomainAllowlists;
189
+ constructor(compiledPolicy, toolAnnotations, protectedPaths, allowedDirectory, serverDomainAllowlists) {
190
+ this.compiledPolicy = compiledPolicy;
191
+ this.protectedPaths = protectedPaths;
192
+ this.allowedDirectory = allowedDirectory;
193
+ this.serverDomainAllowlists = serverDomainAllowlists ?? new Map();
194
+ this.annotationMap = this.buildAnnotationMap(toolAnnotations);
195
+ }
196
+ buildAnnotationMap(annotations) {
197
+ const map = new Map();
198
+ for (const [serverName, serverData] of Object.entries(annotations.servers)) {
199
+ for (const tool of serverData.tools) {
200
+ const key = `${serverName}__${tool.toolName}`;
201
+ map.set(key, tool);
202
+ }
203
+ }
204
+ return map;
205
+ }
206
+ /** Returns the annotation for a tool, or undefined if unknown. */
207
+ getAnnotation(serverName, toolName) {
208
+ return this.annotationMap.get(`${serverName}__${toolName}`);
209
+ }
210
+ evaluate(request) {
211
+ // Phase 1: Structural invariants (may resolve some roles via sandbox containment)
212
+ const structural = this.evaluateStructuralInvariants(request);
213
+ if (structural.decision)
214
+ return structural.decision;
215
+ // Phase 2: Compiled rules (skipping sandbox-resolved roles)
216
+ return this.evaluateCompiledRules(request, structural.sandboxResolvedRoles);
217
+ }
218
+ /**
219
+ * Phase 1: Hardcoded structural invariants.
220
+ *
221
+ * 1a. Protected path check (deny)
222
+ * 1b. Sandbox containment for path-category roles (allow/partial)
223
+ * 1c. Domain allowlist for url-category roles (escalate)
224
+ * 1d. Unknown tool denial (deny)
225
+ *
226
+ * Uses the union of heuristic and annotation-based path extraction
227
+ * for defense-in-depth. Returns a StructuralResult with either a
228
+ * final decision or a set of roles resolved by sandbox containment.
229
+ */
230
+ evaluateStructuralInvariants(request) {
231
+ // Extract paths using both methods for defense-in-depth
232
+ const heuristicPaths = extractPathsHeuristic(request.arguments);
233
+ const annotation = this.annotationMap.get(`${request.serverName}__${request.toolName}`);
234
+ // Phase 1a/1b use path-category roles only (not URL roles)
235
+ const pathRoles = getPathRoles();
236
+ const annotatedPaths = annotation
237
+ ? extractAnnotatedPaths(request.arguments, annotation, pathRoles)
238
+ : [];
239
+ // Union of both extraction methods, deduplicated
240
+ const allPaths = [...new Set([...heuristicPaths, ...annotatedPaths])];
241
+ const resolvedPaths = allPaths.map(p => resolveRealPath(p));
242
+ // Phase 1a: Protected paths -- any match is an immediate deny
243
+ for (const rp of resolvedPaths) {
244
+ if (isProtectedPath(rp, this.protectedPaths)) {
245
+ return finalDecision({
246
+ decision: 'deny',
247
+ rule: 'structural-protected-path',
248
+ reason: `Access to protected path is forbidden: ${rp}`,
249
+ });
250
+ }
251
+ }
252
+ // Phase 1b: Sandbox containment checks (path-category roles)
253
+ //
254
+ // The sandbox auto-allow decision uses annotated paths when annotations
255
+ // exist (not heuristic paths). An arg annotated as 'none' should not
256
+ // grant sandbox containment even if the value looks like a path.
257
+ // Heuristic paths are only used for defense-in-depth on the deny side
258
+ // (Phase 1a protected path check).
259
+ //
260
+ // Only SANDBOX_SAFE_PATH_ROLES (read-path, write-path, delete-path) can
261
+ // be auto-resolved by sandbox containment. Higher-risk path roles like
262
+ // write-history and delete-history always fall through to Phase 2.
263
+ const sandboxResolvedRoles = new Set();
264
+ const resolvedSandboxPaths = annotation
265
+ ? annotatedPaths.map(p => resolveRealPath(p))
266
+ : resolvedPaths;
267
+ // Extract URL args once for use in both Phase 1b (fast-path guard) and Phase 1c
268
+ const urlArgs = annotation
269
+ ? extractAnnotatedUrls(request.arguments, annotation, getUrlRoles())
270
+ : [];
271
+ // Determine if the tool has any non-sandbox-safe path roles
272
+ const toolHasUnsafePathRoles = annotation
273
+ ? pathRoles.some(role => !SANDBOX_SAFE_PATH_ROLES.has(role) &&
274
+ Object.values(annotation.args).some(argRoles => argRoles.includes(role)))
275
+ : false;
276
+ if (this.allowedDirectory && resolvedSandboxPaths.length > 0) {
277
+ // Fast path: all annotated paths within sandbox -> auto-allow
278
+ // Only fires when ALL path roles are sandbox-safe and no URL roles need checking
279
+ const allWithinSandbox = resolvedSandboxPaths.every(rp => isWithinDirectory(rp, this.allowedDirectory));
280
+ if (allWithinSandbox && urlArgs.length === 0 && !toolHasUnsafePathRoles) {
281
+ return finalDecision({
282
+ decision: 'allow',
283
+ rule: 'structural-sandbox-allow',
284
+ reason: `All paths are within the sandbox directory: ${this.allowedDirectory}`,
285
+ });
286
+ }
287
+ // Partial sandbox resolution: check each path role independently.
288
+ // A role is "sandbox-resolved" if every path for that role is within
289
+ // the sandbox. Only sandbox-safe roles can be resolved here.
290
+ // Roles with zero extracted paths are not resolved.
291
+ if (annotation) {
292
+ for (const role of pathRoles) {
293
+ if (!SANDBOX_SAFE_PATH_ROLES.has(role))
294
+ continue;
295
+ const pathsForRole = extractAnnotatedPaths(request.arguments, annotation, [role]);
296
+ if (pathsForRole.length > 0 && pathsForRole.every(p => isWithinDirectory(p, this.allowedDirectory))) {
297
+ sandboxResolvedRoles.add(role);
298
+ }
299
+ }
300
+ }
301
+ }
302
+ // Phase 1c: Domain allowlist for URL-category roles
303
+ if (urlArgs.length > 0) {
304
+ const allowlist = this.serverDomainAllowlists.get(request.serverName);
305
+ if (allowlist) {
306
+ for (const { value, roleDef } of urlArgs) {
307
+ const domain = resolveUrlForDomainCheck(value, roleDef, request.arguments);
308
+ if (!domainMatchesAllowlist(domain, allowlist)) {
309
+ return finalDecision({
310
+ decision: 'escalate',
311
+ rule: 'structural-domain-escalate',
312
+ reason: `URL domain "${domain}" is not in the allowlist for server "${request.serverName}"`,
313
+ });
314
+ }
315
+ }
316
+ // All URLs passed domain check -- mark URL roles as resolved
317
+ for (const { role } of urlArgs) {
318
+ sandboxResolvedRoles.add(role);
319
+ }
320
+ }
321
+ // If no allowlist, URL roles are not structurally restricted -- fall through to Phase 2
322
+ }
323
+ // Phase 1d: Unknown tool check
324
+ if (!annotation) {
325
+ return finalDecision({
326
+ decision: 'deny',
327
+ rule: 'structural-unknown-tool',
328
+ reason: `Unknown tool: ${request.serverName}/${request.toolName}`,
329
+ });
330
+ }
331
+ return { sandboxResolvedRoles: sandboxResolvedRoles.size > 0 ? sandboxResolvedRoles : NO_ROLES_RESOLVED };
332
+ }
333
+ /**
334
+ * Phase 2: Evaluate compiled declarative rules.
335
+ *
336
+ * For tools with multiple roles (e.g., edit_file has read-path + write-path),
337
+ * each role is evaluated independently through the rule chain. The most
338
+ * restrictive result across all roles wins (deny > escalate > allow).
339
+ * Roles already resolved by Phase 1 sandbox containment are skipped.
340
+ *
341
+ * For tools with no roles (e.g., list_allowed_directories), the chain is
342
+ * evaluated once without role filtering.
343
+ */
344
+ evaluateCompiledRules(request, sandboxResolvedRoles) {
345
+ const annotation = this.annotationMap.get(`${request.serverName}__${request.toolName}`);
346
+ const allRoles = collectDistinctRoles(annotation);
347
+ // Filter out roles already resolved by sandbox containment
348
+ const rolesToEvaluate = allRoles.filter(r => !sandboxResolvedRoles.has(r));
349
+ // All resource roles were sandbox-resolved → allow
350
+ if (allRoles.length > 0 && rolesToEvaluate.length === 0) {
351
+ return {
352
+ decision: 'allow',
353
+ rule: 'structural-sandbox-allow',
354
+ reason: 'All path roles resolved by sandbox containment',
355
+ };
356
+ }
357
+ if (rolesToEvaluate.length === 0) {
358
+ // No resource roles at all (e.g., list_allowed_directories)
359
+ return this.evaluateRulesForRole(request, annotation, undefined);
360
+ }
361
+ let mostRestrictive;
362
+ for (const role of rolesToEvaluate) {
363
+ const result = this.evaluateRulesForRole(request, annotation, role);
364
+ if (result.decision === 'deny')
365
+ return result;
366
+ if (!mostRestrictive || DECISION_SEVERITY[result.decision] > DECISION_SEVERITY[mostRestrictive.decision]) {
367
+ mostRestrictive = result;
368
+ }
369
+ }
370
+ return mostRestrictive;
371
+ }
372
+ /**
373
+ * Evaluates the rule chain for a single role (or all roles if undefined).
374
+ *
375
+ * When evaluatingRole is set, only rules that are either role-agnostic
376
+ * (no roles/paths conditions) or relevant to the specified role are
377
+ * considered. First matching rule wins; default deny if none match.
378
+ *
379
+ * For roles with multiple extracted paths, delegates to
380
+ * evaluateRulesForMultiPaths for per-element evaluation.
381
+ */
382
+ evaluateRulesForRole(request, annotation, evaluatingRole) {
383
+ // Per-element evaluation: when a role has multiple paths, each path
384
+ // is independently discharged by the first matching rule.
385
+ if (evaluatingRole !== undefined) {
386
+ const rolePaths = extractAnnotatedPaths(request.arguments, annotation, [evaluatingRole]);
387
+ if (rolePaths.length > 1) {
388
+ return this.evaluateRulesForMultiPaths(request, annotation, evaluatingRole, rolePaths);
389
+ }
390
+ }
391
+ for (const rule of this.compiledPolicy.rules) {
392
+ if (evaluatingRole !== undefined && hasRoleConditions(rule) && !ruleRelevantToRole(rule, evaluatingRole)) {
393
+ continue;
394
+ }
395
+ if (this.ruleMatches(rule, request, annotation)) {
396
+ return {
397
+ decision: rule.then,
398
+ rule: rule.name,
399
+ reason: rule.reason,
400
+ };
401
+ }
402
+ }
403
+ return {
404
+ decision: 'deny',
405
+ rule: 'default-deny',
406
+ reason: 'No matching policy rule -- denied by default',
407
+ };
408
+ }
409
+ /**
410
+ * Per-element path evaluation for roles with multiple paths.
411
+ *
412
+ * Each path is independently "discharged" by the first rule whose
413
+ * paths.within contains it. Rules without path conditions match all
414
+ * remaining paths. The most restrictive decision across all discharged
415
+ * paths wins (deny > escalate > allow). Undischarged paths default-deny.
416
+ */
417
+ evaluateRulesForMultiPaths(request, annotation, role, paths) {
418
+ const remainingPaths = new Set(paths);
419
+ let mostRestrictive;
420
+ for (const rule of this.compiledPolicy.rules) {
421
+ if (remainingPaths.size === 0)
422
+ break;
423
+ // Skip rules not relevant to this role
424
+ if (hasRoleConditions(rule) && !ruleRelevantToRole(rule, role))
425
+ continue;
426
+ // Skip rules whose non-path conditions don't match
427
+ if (!this.ruleMatchesNonPathConditions(rule, request, annotation))
428
+ continue;
429
+ const cond = rule.if;
430
+ let matched;
431
+ if (cond.paths !== undefined) {
432
+ // Rule has a path condition: discharge only paths within the directory
433
+ matched = [];
434
+ for (const p of remainingPaths) {
435
+ if (isWithinDirectory(p, cond.paths.within)) {
436
+ matched.push(p);
437
+ }
438
+ }
439
+ if (matched.length === 0)
440
+ continue;
441
+ }
442
+ else {
443
+ // Rule has no path condition: matches all remaining paths
444
+ matched = [...remainingPaths];
445
+ }
446
+ // Discharge matched paths and record decision
447
+ for (const p of matched)
448
+ remainingPaths.delete(p);
449
+ const result = {
450
+ decision: rule.then,
451
+ rule: rule.name,
452
+ reason: rule.reason,
453
+ };
454
+ if (!mostRestrictive || DECISION_SEVERITY[result.decision] > DECISION_SEVERITY[mostRestrictive.decision]) {
455
+ mostRestrictive = result;
456
+ }
457
+ }
458
+ // Any undischarged paths -> default-deny (deny is the most restrictive decision)
459
+ if (remainingPaths.size > 0) {
460
+ return {
461
+ decision: 'deny',
462
+ rule: 'default-deny',
463
+ reason: 'No matching policy rule -- denied by default',
464
+ };
465
+ }
466
+ return mostRestrictive;
467
+ }
468
+ /**
469
+ * Checks non-path conditions in a rule's `if` block: roles, server, tool, sideEffects.
470
+ */
471
+ ruleMatchesNonPathConditions(rule, request, annotation) {
472
+ const cond = rule.if;
473
+ if (cond.roles !== undefined) {
474
+ const toolHasMatchingRole = Object.values(annotation.args).some(argRoles => argRoles.some(r => cond.roles.includes(r)));
475
+ if (!toolHasMatchingRole)
476
+ return false;
477
+ }
478
+ if (cond.server !== undefined && !cond.server.includes(request.serverName)) {
479
+ return false;
480
+ }
481
+ if (cond.tool !== undefined && !cond.tool.includes(request.toolName)) {
482
+ return false;
483
+ }
484
+ if (cond.sideEffects !== undefined && annotation.sideEffects !== cond.sideEffects) {
485
+ return false;
486
+ }
487
+ return true;
488
+ }
489
+ /**
490
+ * Checks whether all conditions in a rule's `if` block are satisfied.
491
+ */
492
+ ruleMatches(rule, request, annotation) {
493
+ if (!this.ruleMatchesNonPathConditions(rule, request, annotation))
494
+ return false;
495
+ // Check paths condition
496
+ const cond = rule.if;
497
+ if (cond.paths !== undefined) {
498
+ const extracted = extractAnnotatedPaths(request.arguments, annotation, cond.paths.roles);
499
+ // Zero paths extracted = condition not satisfied, rule does not match
500
+ if (extracted.length === 0)
501
+ return false;
502
+ // isWithinDirectory resolves paths internally, no pre-resolution needed
503
+ const allWithin = extracted.every(p => isWithinDirectory(p, cond.paths.within));
504
+ if (!allWithin)
505
+ return false;
506
+ }
507
+ // Check domains condition
508
+ if (cond.domains !== undefined) {
509
+ const urlArgs = extractAnnotatedUrls(request.arguments, annotation, cond.domains.roles);
510
+ // Zero URL args extracted = condition not satisfied, rule does not match
511
+ if (urlArgs.length === 0)
512
+ return false;
513
+ const allMatch = urlArgs.every(({ value, roleDef }) => {
514
+ const domain = resolveUrlForDomainCheck(value, roleDef, request.arguments);
515
+ return domainMatchesAllowlist(domain, cond.domains.allowed);
516
+ });
517
+ if (!allMatch)
518
+ return false;
519
+ }
520
+ return true;
521
+ }
522
+ }
523
+ //# sourceMappingURL=policy-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../../src/trusted-process/policy-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { CompiledPolicyFile } from '../pipeline/types.js';
2
+ /**
3
+ * Root entry for the MCP Roots protocol.
4
+ * Mirrors the MCP SDK's Root type without importing it directly,
5
+ * keeping this module free of SDK dependencies.
6
+ */
7
+ export interface PolicyRoot {
8
+ /** Absolute directory path (not a file:// URI yet -- callers convert). */
9
+ readonly path: string;
10
+ /** Human-readable label for debugging and audit logs. */
11
+ readonly name: string;
12
+ }
13
+ /**
14
+ * Extracts the set of directories that the compiled policy references
15
+ * in `allow` or `escalate` rules with `paths.within` conditions.
16
+ * These directories, plus the sandbox, form the initial roots that
17
+ * MCP servers should accept.
18
+ *
19
+ * `deny` rules are excluded -- they never grant access, so exposing
20
+ * denied directories as roots would widen the server-side boundary
21
+ * without purpose.
22
+ *
23
+ * Catch-all rules without `paths.within` (like
24
+ * `escalate-read-outside-permitted-areas`) are also excluded from
25
+ * initial roots. Those are handled dynamically: when a human approves
26
+ * an escalation, the target directory is added as a root at that time.
27
+ *
28
+ * @param compiledPolicy - The loaded compiled policy artifact.
29
+ * @param allowedDirectory - The sandbox directory (always included).
30
+ * @returns Deduplicated array of PolicyRoot entries, sandbox first.
31
+ */
32
+ export declare function extractPolicyRoots(compiledPolicy: CompiledPolicyFile, allowedDirectory: string): PolicyRoot[];
33
+ /**
34
+ * Converts PolicyRoot entries to MCP Root objects with `file://` URIs.
35
+ */
36
+ export declare function toMcpRoots(policyRoots: PolicyRoot[]): Array<{
37
+ uri: string;
38
+ name: string;
39
+ }>;
40
+ /**
41
+ * Extracts the containing directory for a filesystem path.
42
+ * Used to derive the root directory when a human approves an
43
+ * escalation -- the approved path's parent directory becomes a root
44
+ * so the filesystem server will accept the forwarded call.
45
+ *
46
+ * If the path ends with a trailing slash, it is treated as a directory
47
+ * and returned as-is (without the trailing slash) after resolution.
48
+ * Otherwise dirname is used to get the containing directory.
49
+ */
50
+ export declare function directoryForPath(filePath: string): string;
@@ -0,0 +1,67 @@
1
+ import { dirname } from 'node:path';
2
+ import { resolveRealPath } from '../types/argument-roles.js';
3
+ /**
4
+ * Extracts the set of directories that the compiled policy references
5
+ * in `allow` or `escalate` rules with `paths.within` conditions.
6
+ * These directories, plus the sandbox, form the initial roots that
7
+ * MCP servers should accept.
8
+ *
9
+ * `deny` rules are excluded -- they never grant access, so exposing
10
+ * denied directories as roots would widen the server-side boundary
11
+ * without purpose.
12
+ *
13
+ * Catch-all rules without `paths.within` (like
14
+ * `escalate-read-outside-permitted-areas`) are also excluded from
15
+ * initial roots. Those are handled dynamically: when a human approves
16
+ * an escalation, the target directory is added as a root at that time.
17
+ *
18
+ * @param compiledPolicy - The loaded compiled policy artifact.
19
+ * @param allowedDirectory - The sandbox directory (always included).
20
+ * @returns Deduplicated array of PolicyRoot entries, sandbox first.
21
+ */
22
+ export function extractPolicyRoots(compiledPolicy, allowedDirectory) {
23
+ const seen = new Set();
24
+ const roots = [];
25
+ // Sandbox is always the first root.
26
+ const resolvedSandbox = resolveRealPath(allowedDirectory);
27
+ seen.add(resolvedSandbox);
28
+ roots.push({ path: resolvedSandbox, name: 'sandbox' });
29
+ for (const rule of compiledPolicy.rules) {
30
+ if (rule.then === 'deny')
31
+ continue;
32
+ if (!rule.if.paths?.within)
33
+ continue;
34
+ const dir = resolveRealPath(rule.if.paths.within);
35
+ if (seen.has(dir))
36
+ continue;
37
+ seen.add(dir);
38
+ roots.push({ path: dir, name: rule.name });
39
+ }
40
+ return roots;
41
+ }
42
+ /**
43
+ * Converts PolicyRoot entries to MCP Root objects with `file://` URIs.
44
+ */
45
+ export function toMcpRoots(policyRoots) {
46
+ return policyRoots.map(r => ({
47
+ uri: `file://${r.path}`,
48
+ name: r.name,
49
+ }));
50
+ }
51
+ /**
52
+ * Extracts the containing directory for a filesystem path.
53
+ * Used to derive the root directory when a human approves an
54
+ * escalation -- the approved path's parent directory becomes a root
55
+ * so the filesystem server will accept the forwarded call.
56
+ *
57
+ * If the path ends with a trailing slash, it is treated as a directory
58
+ * and returned as-is (without the trailing slash) after resolution.
59
+ * Otherwise dirname is used to get the containing directory.
60
+ */
61
+ export function directoryForPath(filePath) {
62
+ // Check for trailing slash before resolving, since resolveRealPath() strips it.
63
+ if (filePath.endsWith('/'))
64
+ return resolveRealPath(filePath);
65
+ return dirname(resolveRealPath(filePath));
66
+ }
67
+ //# sourceMappingURL=policy-roots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-roots.js","sourceRoot":"","sources":["../../src/trusted-process/policy-roots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAc7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,kBAAkB,CAChC,cAAkC,EAClC,gBAAwB;IAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAiB,EAAE,CAAC;IAE/B,oCAAoC;IACpC,MAAM,eAAe,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;IAC1D,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IAEvD,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACnC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM;YAAE,SAAS;QAErC,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAClD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAE5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,WAAyB;IAEzB,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3B,GAAG,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE;QACvB,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,gFAAgF;IAChF,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC7D,OAAO,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5C,CAAC"}