@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,6 @@
1
+ import type { PolicyDecisionStatus } from '../types/mcp.js';
2
+ export interface EvaluationResult {
3
+ decision: PolicyDecisionStatus;
4
+ rule: string;
5
+ reason: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=policy-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-types.js","sourceRoot":"","sources":["../../src/trusted-process/policy-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Sandbox Integration -- Wraps MCP server processes in OS-level sandboxes.
3
+ *
4
+ * Each sandboxed server is spawned via a separate `srt` CLI process with
5
+ * its own settings file, giving each server independent sandbox infrastructure
6
+ * (filesystem restrictions, network proxy, and process isolation).
7
+ *
8
+ * The proxy process itself never calls SandboxManager.initialize() -- it
9
+ * only uses the stateless isSupportedPlatform() and checkDependencies()
10
+ * for the availability check.
11
+ */
12
+ import type { MCPServerConfig, SandboxAvailabilityPolicy } from '../config/types.js';
13
+ /**
14
+ * Result of resolving a server's sandbox configuration.
15
+ * Discriminated union: sandboxed servers carry the resolved config,
16
+ * unsandboxed servers carry the reason they were exempted.
17
+ */
18
+ export type ResolvedSandboxConfig = {
19
+ readonly sandboxed: true;
20
+ readonly config: ResolvedSandboxParams;
21
+ } | {
22
+ readonly sandboxed: false;
23
+ readonly reason: 'opt-out' | 'platform-unavailable';
24
+ };
25
+ /**
26
+ * Fully resolved sandbox parameters ready for srt settings.
27
+ * All relative paths have been resolved to absolute paths.
28
+ * The session sandbox directory has been injected into allowWrite.
29
+ */
30
+ export interface ResolvedSandboxParams {
31
+ readonly allowWrite: readonly string[];
32
+ readonly denyRead: readonly string[];
33
+ readonly denyWrite: readonly string[];
34
+ readonly network: false | {
35
+ readonly allowedDomains: readonly string[];
36
+ readonly deniedDomains: readonly string[];
37
+ };
38
+ }
39
+ /** Result of checking sandbox-runtime availability. */
40
+ export interface SandboxAvailabilityResult {
41
+ readonly platformSupported: boolean;
42
+ readonly errors: string[];
43
+ readonly warnings: string[];
44
+ }
45
+ /**
46
+ * Checks sandbox dependencies and returns a structured result.
47
+ *
48
+ * Wraps SandboxManager.isSupportedPlatform() and checkDependencies()
49
+ * into a single call. Does NOT throw -- callers inspect the result and
50
+ * decide based on sandboxPolicy.
51
+ */
52
+ export declare function checkSandboxAvailability(): SandboxAvailabilityResult;
53
+ /**
54
+ * Resolves the effective sandbox configuration for a single MCP server.
55
+ *
56
+ * Applies defaults when `sandbox` is omitted, injects the session
57
+ * sandbox directory into allowWrite, and resolves relative paths.
58
+ */
59
+ export declare function resolveSandboxConfig(serverConfig: MCPServerConfig, sessionSandboxDir: string, platformAvailable: boolean, policy: SandboxAvailabilityPolicy): ResolvedSandboxConfig;
60
+ /**
61
+ * Writes a per-server srt settings JSON file.
62
+ *
63
+ * Each sandboxed server gets its own settings file at
64
+ * `{settingsDir}/{serverName}.srt-settings.json`.
65
+ *
66
+ * Returns the absolute path to the written file.
67
+ */
68
+ export declare function writeServerSettings(serverName: string, config: ResolvedSandboxParams, settingsDir: string): string;
69
+ /**
70
+ * Transforms a server's spawn parameters (command + args) into a
71
+ * sandbox-wrapped command suitable for StdioClientTransport.
72
+ *
73
+ * For sandboxed servers: returns `{ command: 'srt', args: ['-s', settingsPath, '-c', escapedCmd] }`.
74
+ * For unsandboxed servers: returns the original command/args unchanged.
75
+ */
76
+ export declare function wrapServerCommand(serverName: string, command: string, args: readonly string[], sandboxConfig: ResolvedSandboxConfig, settingsDir: string): {
77
+ command: string;
78
+ args: string[];
79
+ };
80
+ /**
81
+ * Cleans up per-server settings files created by writeServerSettings().
82
+ * Called during proxy shutdown. Safe to call even if no files were written.
83
+ */
84
+ export declare function cleanupSettingsFiles(settingsDir: string): void;
85
+ /**
86
+ * Annotates an MCP error response when it looks like a sandbox block.
87
+ *
88
+ * When a sandboxed server returns an error matching common sandbox-blocked
89
+ * patterns (EPERM, EACCES, etc.) and the policy engine had allowed the call,
90
+ * this prefixes the error with [SANDBOX BLOCKED] to signal OS containment.
91
+ */
92
+ export declare function annotateSandboxViolation(errorMessage: string, serverSandboxed: boolean): string;
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Sandbox Integration -- Wraps MCP server processes in OS-level sandboxes.
3
+ *
4
+ * Each sandboxed server is spawned via a separate `srt` CLI process with
5
+ * its own settings file, giving each server independent sandbox infrastructure
6
+ * (filesystem restrictions, network proxy, and process isolation).
7
+ *
8
+ * The proxy process itself never calls SandboxManager.initialize() -- it
9
+ * only uses the stateless isSupportedPlatform() and checkDependencies()
10
+ * for the availability check.
11
+ */
12
+ import { SandboxManager } from '@anthropic-ai/sandbox-runtime';
13
+ import { writeFileSync, rmSync, existsSync } from 'node:fs';
14
+ import { join, resolve, dirname, isAbsolute } from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { quote } from 'shell-quote';
17
+ // ── Constants ──────────────────────────────────────────────────────────────
18
+ /** Sensitive directories blocked from reads by default. */
19
+ const DEFAULT_DENY_READ = ['~/.ssh', '~/.gnupg', '~/.aws'];
20
+ /**
21
+ * Resolve the absolute path to the `srt` binary in node_modules.
22
+ * Walks up from the package root to handle npm's dependency hoisting,
23
+ * where bins may be in a parent node_modules/.bin/ directory.
24
+ */
25
+ const __sandboxDirname = dirname(fileURLToPath(import.meta.url));
26
+ const SRT_BIN = resolveNodeModulesBin('srt', resolve(__sandboxDirname, '..', '..'));
27
+ /** Pattern matching common OS-level permission errors from sandbox containment. */
28
+ const SANDBOX_BLOCK_PATTERN = /EACCES|EPERM|Operation not permitted|Permission denied|read-only file system/i;
29
+ // ── Public API ─────────────────────────────────────────────────────────────
30
+ /**
31
+ * Checks sandbox dependencies and returns a structured result.
32
+ *
33
+ * Wraps SandboxManager.isSupportedPlatform() and checkDependencies()
34
+ * into a single call. Does NOT throw -- callers inspect the result and
35
+ * decide based on sandboxPolicy.
36
+ */
37
+ export function checkSandboxAvailability() {
38
+ const platformSupported = SandboxManager.isSupportedPlatform();
39
+ if (!platformSupported) {
40
+ return { platformSupported, errors: [], warnings: [] };
41
+ }
42
+ const { errors, warnings } = SandboxManager.checkDependencies();
43
+ return { platformSupported, errors, warnings };
44
+ }
45
+ /**
46
+ * Resolves the effective sandbox configuration for a single MCP server.
47
+ *
48
+ * Applies defaults when `sandbox` is omitted, injects the session
49
+ * sandbox directory into allowWrite, and resolves relative paths.
50
+ */
51
+ export function resolveSandboxConfig(serverConfig, sessionSandboxDir, platformAvailable, policy) {
52
+ if (serverConfig.sandbox === false) {
53
+ return { sandboxed: false, reason: 'opt-out' };
54
+ }
55
+ if (!platformAvailable) {
56
+ if (policy === 'enforce') {
57
+ throw new Error('[sandbox] Server requires sandboxing but platform is unavailable ' +
58
+ 'and sandboxPolicy is "enforce".');
59
+ }
60
+ return { sandboxed: false, reason: 'platform-unavailable' };
61
+ }
62
+ const sandboxConfig = serverConfig.sandbox ?? {};
63
+ const fsConfig = sandboxConfig.filesystem ?? {};
64
+ const networkConfig = sandboxConfig.network;
65
+ const allowWrite = buildAllowWrite(sessionSandboxDir, fsConfig.allowWrite ?? []);
66
+ const denyRead = fsConfig.denyRead ?? DEFAULT_DENY_READ;
67
+ const denyWrite = fsConfig.denyWrite ?? [];
68
+ const network = resolveNetworkConfig(networkConfig);
69
+ return {
70
+ sandboxed: true,
71
+ config: { allowWrite, denyRead, denyWrite, network },
72
+ };
73
+ }
74
+ /**
75
+ * Writes a per-server srt settings JSON file.
76
+ *
77
+ * Each sandboxed server gets its own settings file at
78
+ * `{settingsDir}/{serverName}.srt-settings.json`.
79
+ *
80
+ * Returns the absolute path to the written file.
81
+ */
82
+ export function writeServerSettings(serverName, config, settingsDir) {
83
+ const settingsPath = join(settingsDir, `${serverName}.srt-settings.json`);
84
+ const network = config.network === false
85
+ ? { allowedDomains: [], deniedDomains: [] }
86
+ : { allowedDomains: config.network.allowedDomains, deniedDomains: config.network.deniedDomains };
87
+ const settings = {
88
+ network,
89
+ filesystem: {
90
+ denyRead: config.denyRead,
91
+ allowWrite: config.allowWrite,
92
+ denyWrite: config.denyWrite,
93
+ },
94
+ };
95
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
96
+ return settingsPath;
97
+ }
98
+ /**
99
+ * Transforms a server's spawn parameters (command + args) into a
100
+ * sandbox-wrapped command suitable for StdioClientTransport.
101
+ *
102
+ * For sandboxed servers: returns `{ command: 'srt', args: ['-s', settingsPath, '-c', escapedCmd] }`.
103
+ * For unsandboxed servers: returns the original command/args unchanged.
104
+ */
105
+ export function wrapServerCommand(serverName, command, args, sandboxConfig, settingsDir) {
106
+ if (!sandboxConfig.sandboxed) {
107
+ return { command, args: [...args] };
108
+ }
109
+ const settingsPath = join(settingsDir, `${serverName}.srt-settings.json`);
110
+ // Resolve relative paths in args to absolute so the command works when
111
+ // the proxy sets cwd to the sandbox directory.
112
+ const resolvedArgs = args.map(a => (!isAbsolute(a) && !a.startsWith('-') ? resolve(a) : a));
113
+ const cmdString = quote([command, ...resolvedArgs]);
114
+ return {
115
+ command: SRT_BIN,
116
+ args: ['-s', settingsPath, '-c', cmdString],
117
+ };
118
+ }
119
+ /**
120
+ * Cleans up per-server settings files created by writeServerSettings().
121
+ * Called during proxy shutdown. Safe to call even if no files were written.
122
+ */
123
+ export function cleanupSettingsFiles(settingsDir) {
124
+ try {
125
+ rmSync(settingsDir, { recursive: true, force: true });
126
+ }
127
+ catch {
128
+ // Best-effort cleanup; OS temp rotation handles leftovers
129
+ }
130
+ }
131
+ /**
132
+ * Annotates an MCP error response when it looks like a sandbox block.
133
+ *
134
+ * When a sandboxed server returns an error matching common sandbox-blocked
135
+ * patterns (EPERM, EACCES, etc.) and the policy engine had allowed the call,
136
+ * this prefixes the error with [SANDBOX BLOCKED] to signal OS containment.
137
+ */
138
+ export function annotateSandboxViolation(errorMessage, serverSandboxed) {
139
+ if (!serverSandboxed)
140
+ return errorMessage;
141
+ if (!SANDBOX_BLOCK_PATTERN.test(errorMessage))
142
+ return errorMessage;
143
+ return `[SANDBOX BLOCKED] ${errorMessage}`;
144
+ }
145
+ // ── Internal helpers ───────────────────────────────────────────────────────
146
+ /**
147
+ * Builds the allowWrite list with the session sandbox dir always included.
148
+ * Relative paths are resolved against the session sandbox directory.
149
+ */
150
+ function buildAllowWrite(sessionSandboxDir, additionalPaths) {
151
+ const resolved = additionalPaths.map(p => isAbsolute(p) ? p : resolve(sessionSandboxDir, p));
152
+ return [sessionSandboxDir, ...resolved];
153
+ }
154
+ /**
155
+ * Resolves network config to the canonical form.
156
+ * `undefined` and `false` both mean no network access.
157
+ */
158
+ function resolveNetworkConfig(config) {
159
+ if (!config)
160
+ return false;
161
+ return {
162
+ allowedDomains: config.allowedDomains,
163
+ deniedDomains: config.deniedDomains ?? [],
164
+ };
165
+ }
166
+ /**
167
+ * Resolves a binary name in node_modules/.bin/ by walking up from startDir.
168
+ * Handles npm's dependency hoisting where bins may live in a parent node_modules/.bin/.
169
+ */
170
+ function resolveNodeModulesBin(binName, startDir) {
171
+ let dir = startDir;
172
+ for (;;) {
173
+ const candidate = join(dir, 'node_modules', '.bin', binName);
174
+ if (existsSync(candidate))
175
+ return candidate;
176
+ const parent = dirname(dir);
177
+ if (parent === dir)
178
+ break;
179
+ dir = parent;
180
+ }
181
+ // Fallback: assume it's directly under the package root
182
+ return join(startDir, 'node_modules', '.bin', binName);
183
+ }
184
+ //# sourceMappingURL=sandbox-integration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox-integration.js","sourceRoot":"","sources":["../../src/trusted-process/sandbox-integration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * ArgumentRole Registry -- Central definition of argument role semantics.
3
+ *
4
+ * Each role is paired with metadata describing its security semantics
5
+ * and a normalizer function for canonicalizing argument values. This
6
+ * eliminates scattered hardcoded role strings and enables annotation-driven
7
+ * normalization instead of fragile heuristics.
8
+ *
9
+ * Roles are organized into categories that determine which structural
10
+ * invariant applies in the policy engine:
11
+ * - path: filesystem path containment checks
12
+ * - url: domain allowlist checks
13
+ * - opaque: no structural invariant (semantic meaning only)
14
+ */
15
+ export type RoleCategory = 'path' | 'url' | 'opaque';
16
+ export type ArgumentRole = 'read-path' | 'write-path' | 'delete-path' | 'write-history' | 'delete-history' | 'fetch-url' | 'git-remote-url' | 'branch-name' | 'commit-message' | 'none';
17
+ export interface RoleDefinition {
18
+ readonly description: string;
19
+ readonly isResourceIdentifier: boolean;
20
+ readonly category: RoleCategory;
21
+ readonly normalize: (value: string) => string;
22
+ /** Extract the policy-relevant value (e.g., domain from URL). */
23
+ readonly prepareForPolicy?: (value: string) => string;
24
+ /**
25
+ * Context-aware resolution for values that need sibling arguments.
26
+ * E.g., resolving named git remote "origin" to its URL using the
27
+ * `path` argument from the same tool call.
28
+ */
29
+ readonly resolveForPolicy?: (value: string, allArgs: Record<string, unknown>) => string;
30
+ /**
31
+ * Guidance for the LLM annotation prompt. Built into the prompt
32
+ * dynamically from the registry -- no manual prompt maintenance.
33
+ */
34
+ readonly annotationGuidance: string;
35
+ /**
36
+ * When set, this role is only relevant for the named MCP servers.
37
+ * Roles without serverNames are universal (included for all servers).
38
+ */
39
+ readonly serverNames?: readonly string[];
40
+ }
41
+ /** Expands a leading `~` or `~/` to the current user's home directory. */
42
+ export declare function expandTilde(filePath: string): string;
43
+ /**
44
+ * Resolves a filesystem path to its canonical real path, following symlinks.
45
+ *
46
+ * Tries three strategies in order:
47
+ * 1. `realpathSync(path)` — works for existing paths, follows all symlinks
48
+ * 2. `realpathSync(parent) + basename` — works for new files in existing dirs
49
+ * 3. `path.resolve(path)` — fallback for entirely new paths
50
+ *
51
+ * This is security-critical: without symlink resolution, a symlinked
52
+ * directory inside the sandbox could escape containment checks.
53
+ */
54
+ export declare function resolveRealPath(filePath: string): string;
55
+ /** Tilde expansion + symlink resolution to produce a canonical real path. */
56
+ export declare function normalizePath(value: string): string;
57
+ /** Normalizes an HTTP(S) URL to a canonical form. Returns value as-is on parse failure. */
58
+ export declare function normalizeUrl(value: string): string;
59
+ /** Extracts the hostname from an HTTP(S) URL. Returns value as-is on parse failure. */
60
+ export declare function extractDomain(value: string): string;
61
+ /** Normalizes a git URL (HTTP or SSH format). SSH URLs are returned as-is. */
62
+ export declare function normalizeGitUrl(value: string): string;
63
+ /** Extracts the domain from a git URL (HTTP or SSH format). */
64
+ export declare function extractGitDomain(value: string): string;
65
+ /**
66
+ * Resolves a git remote value to a URL for policy evaluation.
67
+ *
68
+ * If the value is already a URL (contains :// or matches SSH pattern),
69
+ * returns it as-is. Otherwise, treats it as a named remote and runs
70
+ * `git remote get-url <name>` in the repository directory (found via
71
+ * the `path` sibling argument).
72
+ *
73
+ * Uses execFileSync (not execSync) to avoid command injection --
74
+ * the value comes from agent-controlled tool call arguments.
75
+ *
76
+ * When resolution fails (repo doesn't exist, remote not found, git
77
+ * not installed), returns the original value. This causes the domain
78
+ * check to escalate (the value won't match any allowed domain),
79
+ * which is the correct behavior -- escalate when we can't verify.
80
+ */
81
+ export declare function resolveGitRemote(value: string, allArgs: Record<string, unknown>): string;
82
+ export declare const ARGUMENT_ROLE_REGISTRY: ReadonlyMap<ArgumentRole, RoleDefinition>;
83
+ /** Returns the RoleDefinition for a role. Throws if not registered. */
84
+ export declare function getRoleDefinition(role: ArgumentRole): RoleDefinition;
85
+ /** Returns all roles where isResourceIdentifier is true. */
86
+ export declare function getResourceRoles(): ArgumentRole[];
87
+ /** Type guard: returns true if the value is a valid ArgumentRole string. */
88
+ export declare function isArgumentRole(value: string): value is ArgumentRole;
89
+ /** All role values as a tuple for z.enum() compatibility. */
90
+ export declare function getArgumentRoleValues(): [ArgumentRole, ...ArgumentRole[]];
91
+ /**
92
+ * Returns roles relevant to a specific MCP server.
93
+ * Universal roles (no serverNames) are always included.
94
+ * Server-specific roles are included only when the server matches.
95
+ */
96
+ export declare function getRolesForServer(serverName: string): [ArgumentRole, RoleDefinition][];
97
+ /** Returns all roles with the given category. */
98
+ export declare function getRolesByCategory(category: RoleCategory): ArgumentRole[];
99
+ /** Returns path-category roles only. Used by Phase 1a/1b structural invariants. */
100
+ export declare function getPathRoles(): ArgumentRole[];
101
+ /** Returns url-category roles only. Used by Phase 1c domain checks. */
102
+ export declare function getUrlRoles(): ArgumentRole[];
103
+ /**
104
+ * Path roles that Phase 1b sandbox containment is allowed to auto-resolve.
105
+ *
106
+ * Basic filesystem operations (read, write, delete) are safe within the
107
+ * sandbox boundary. Higher-risk path roles like `write-history` and
108
+ * `delete-history` are NOT sandbox-safe: even when the repo path is inside
109
+ * the sandbox, these operations require Phase 2 policy evaluation (and
110
+ * typically human approval) because they can destroy git history.
111
+ */
112
+ export declare const SANDBOX_SAFE_PATH_ROLES: ReadonlySet<ArgumentRole>;