@provos/ironcurtain 0.4.1 → 0.5.1

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 (146) hide show
  1. package/README.md +219 -248
  2. package/dist/cli.js +10 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/config-command.js +144 -6
  5. package/dist/config/config-command.js.map +1 -1
  6. package/dist/config/constitution-user-base.md +2 -0
  7. package/dist/config/first-start.js +77 -12
  8. package/dist/config/first-start.js.map +1 -1
  9. package/dist/config/generated/compiled-policy.json +199 -72
  10. package/dist/config/generated/tool-annotations.json +1018 -36
  11. package/dist/config/mcp-servers.json +10 -0
  12. package/dist/config/paths.d.ts +31 -0
  13. package/dist/config/paths.js +52 -2
  14. package/dist/config/paths.js.map +1 -1
  15. package/dist/config/types.d.ts +8 -0
  16. package/dist/config/user-config.d.ts +21 -3
  17. package/dist/config/user-config.js +34 -3
  18. package/dist/config/user-config.js.map +1 -1
  19. package/dist/docker/adapters/claude-code.js +104 -23
  20. package/dist/docker/adapters/claude-code.js.map +1 -1
  21. package/dist/docker/agent-adapter.d.ts +24 -1
  22. package/dist/docker/agent-adapter.js +6 -1
  23. package/dist/docker/agent-adapter.js.map +1 -1
  24. package/dist/docker/docker-agent-session.d.ts +16 -9
  25. package/dist/docker/docker-agent-session.js +64 -90
  26. package/dist/docker/docker-agent-session.js.map +1 -1
  27. package/dist/docker/docker-infrastructure.d.ts +51 -0
  28. package/dist/docker/docker-infrastructure.js +261 -0
  29. package/dist/docker/docker-infrastructure.js.map +1 -0
  30. package/dist/docker/docker-manager.js +3 -0
  31. package/dist/docker/docker-manager.js.map +1 -1
  32. package/dist/docker/mitm-proxy.js +4 -0
  33. package/dist/docker/mitm-proxy.js.map +1 -1
  34. package/dist/docker/oauth-credentials.d.ts +81 -0
  35. package/dist/docker/oauth-credentials.js +178 -0
  36. package/dist/docker/oauth-credentials.js.map +1 -0
  37. package/dist/docker/orientation.d.ts +1 -1
  38. package/dist/docker/orientation.js +3 -2
  39. package/dist/docker/orientation.js.map +1 -1
  40. package/dist/docker/provider-config.d.ts +3 -0
  41. package/dist/docker/provider-config.js +28 -0
  42. package/dist/docker/provider-config.js.map +1 -1
  43. package/dist/docker/pty-session.d.ts +27 -0
  44. package/dist/docker/pty-session.js +510 -0
  45. package/dist/docker/pty-session.js.map +1 -0
  46. package/dist/docker/pty-types.d.ts +24 -0
  47. package/dist/docker/pty-types.js +12 -0
  48. package/dist/docker/pty-types.js.map +1 -0
  49. package/dist/docker/types.d.ts +6 -0
  50. package/dist/escalation/escalation-watcher.d.ts +44 -0
  51. package/dist/escalation/escalation-watcher.js +92 -0
  52. package/dist/escalation/escalation-watcher.js.map +1 -0
  53. package/dist/escalation/listener-command.d.ts +10 -0
  54. package/dist/escalation/listener-command.js +407 -0
  55. package/dist/escalation/listener-command.js.map +1 -0
  56. package/dist/escalation/listener-state.d.ts +49 -0
  57. package/dist/escalation/listener-state.js +104 -0
  58. package/dist/escalation/listener-state.js.map +1 -0
  59. package/dist/escalation/session-registry.d.ts +17 -0
  60. package/dist/escalation/session-registry.js +98 -0
  61. package/dist/escalation/session-registry.js.map +1 -0
  62. package/dist/index.js +15 -0
  63. package/dist/index.js.map +1 -1
  64. package/dist/logger.js +2 -3
  65. package/dist/logger.js.map +1 -1
  66. package/dist/pipeline/annotate.js +35 -15
  67. package/dist/pipeline/annotate.js.map +1 -1
  68. package/dist/pipeline/constitution-customizer.d.ts +2 -1
  69. package/dist/pipeline/constitution-customizer.js +36 -3
  70. package/dist/pipeline/constitution-customizer.js.map +1 -1
  71. package/dist/pipeline/github-identity.d.ts +38 -0
  72. package/dist/pipeline/github-identity.js +64 -0
  73. package/dist/pipeline/github-identity.js.map +1 -0
  74. package/dist/pipeline/handwritten-scenarios.js +34 -0
  75. package/dist/pipeline/handwritten-scenarios.js.map +1 -1
  76. package/dist/sandbox/index.js +14 -3
  77. package/dist/sandbox/index.js.map +1 -1
  78. package/dist/servers/fetch-server.js +2 -2
  79. package/dist/session/base-transport.d.ts +19 -0
  80. package/dist/session/base-transport.js +36 -0
  81. package/dist/session/base-transport.js.map +1 -0
  82. package/dist/session/cli-transport.d.ts +3 -3
  83. package/dist/session/cli-transport.js +7 -4
  84. package/dist/session/cli-transport.js.map +1 -1
  85. package/dist/session/index.js +24 -78
  86. package/dist/session/index.js.map +1 -1
  87. package/dist/session/interaction-log.d.ts +13 -0
  88. package/dist/session/interaction-log.js +28 -0
  89. package/dist/session/interaction-log.js.map +1 -0
  90. package/dist/session/preflight.d.ts +3 -0
  91. package/dist/session/preflight.js +39 -18
  92. package/dist/session/preflight.js.map +1 -1
  93. package/dist/session/types.d.ts +2 -0
  94. package/dist/signal/bot-command.js +5 -0
  95. package/dist/signal/bot-command.js.map +1 -1
  96. package/dist/signal/format.d.ts +21 -1
  97. package/dist/signal/format.js +41 -3
  98. package/dist/signal/format.js.map +1 -1
  99. package/dist/signal/signal-bot-daemon.d.ts +53 -18
  100. package/dist/signal/signal-bot-daemon.js +344 -106
  101. package/dist/signal/signal-bot-daemon.js.map +1 -1
  102. package/dist/signal/signal-config.d.ts +4 -0
  103. package/dist/signal/signal-config.js +2 -0
  104. package/dist/signal/signal-config.js.map +1 -1
  105. package/dist/signal/signal-transport.d.ts +13 -7
  106. package/dist/signal/signal-transport.js +36 -12
  107. package/dist/signal/signal-transport.js.map +1 -1
  108. package/dist/trusted-process/audit-log.d.ts +6 -1
  109. package/dist/trusted-process/audit-log.js +22 -2
  110. package/dist/trusted-process/audit-log.js.map +1 -1
  111. package/dist/trusted-process/audit-redactor.d.ts +25 -0
  112. package/dist/trusted-process/audit-redactor.js +121 -0
  113. package/dist/trusted-process/audit-redactor.js.map +1 -0
  114. package/dist/trusted-process/escalation.d.ts +1 -1
  115. package/dist/trusted-process/escalation.js +6 -1
  116. package/dist/trusted-process/escalation.js.map +1 -1
  117. package/dist/trusted-process/index.d.ts +2 -1
  118. package/dist/trusted-process/index.js +47 -6
  119. package/dist/trusted-process/index.js.map +1 -1
  120. package/dist/trusted-process/mcp-client-manager.js +14 -2
  121. package/dist/trusted-process/mcp-client-manager.js.map +1 -1
  122. package/dist/trusted-process/mcp-error-utils.d.ts +11 -0
  123. package/dist/trusted-process/mcp-error-utils.js +50 -0
  124. package/dist/trusted-process/mcp-error-utils.js.map +1 -0
  125. package/dist/trusted-process/mcp-proxy-server.d.ts +4 -2
  126. package/dist/trusted-process/mcp-proxy-server.js +56 -13
  127. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  128. package/dist/trusted-process/path-utils.d.ts +15 -0
  129. package/dist/trusted-process/path-utils.js +38 -0
  130. package/dist/trusted-process/path-utils.js.map +1 -1
  131. package/dist/trusted-process/sandbox-integration.d.ts +5 -0
  132. package/dist/trusted-process/sandbox-integration.js +1 -1
  133. package/dist/trusted-process/sandbox-integration.js.map +1 -1
  134. package/dist/trusted-process/server-context.d.ts +21 -0
  135. package/dist/trusted-process/server-context.js +42 -0
  136. package/dist/trusted-process/server-context.js.map +1 -0
  137. package/dist/types/argument-roles.d.ts +5 -2
  138. package/dist/types/argument-roles.js +25 -2
  139. package/dist/types/argument-roles.js.map +1 -1
  140. package/docker/Dockerfile.claude-code +8 -3
  141. package/docker/entrypoint-claude-code.sh +64 -4
  142. package/package.json +16 -8
  143. package/src/config/constitution-user-base.md +2 -0
  144. package/src/config/generated/compiled-policy.json +199 -72
  145. package/src/config/generated/tool-annotations.json +1018 -36
  146. package/src/config/mcp-servers.json +10 -0
@@ -0,0 +1,510 @@
1
+ /**
2
+ * PTY session module -- orchestrates a Docker session where the user's
3
+ * terminal is attached directly to Claude Code's PTY inside the container.
4
+ *
5
+ * Instead of the batch-oriented DockerAgentSession (docker exec per turn),
6
+ * this module provides a native interactive experience by bridging the
7
+ * terminal via a Node.js PTY proxy to a socat-managed PTY inside the container.
8
+ *
9
+ * Architecture:
10
+ * User terminal -> Node.js PTY proxy -> UDS/TCP -> socat (container)
11
+ * -> Claude Code (interactive, with PTY)
12
+ * -> Code Mode Proxy (MCP)
13
+ * -> mcp-proxy-server (PolicyEngine + Audit)
14
+ */
15
+ import { createConnection } from 'node:net';
16
+ import { execFile } from 'node:child_process';
17
+ import { mkdirSync, writeFileSync, unlinkSync } from 'node:fs';
18
+ import { resolve } from 'node:path';
19
+ import chalk from 'chalk';
20
+ import ora from 'ora';
21
+ import { createSessionId } from '../session/types.js';
22
+ import { CONTAINER_WORKSPACE_DIR } from './agent-adapter.js';
23
+ import { PTY_SOCK_NAME, DEFAULT_PTY_PORT } from './pty-types.js';
24
+ import { createEscalationWatcher, atomicWriteJsonSync } from '../escalation/escalation-watcher.js';
25
+ import { getSessionDir, getSessionSandboxDir, getSessionEscalationDir, getSessionAuditLogPath, getSessionLogPath, getSessionLlmLogPath, getPtyRegistryDir, } from '../config/paths.js';
26
+ import * as logger from '../logger.js';
27
+ /** Maximum time to wait for the PTY socket to appear (ms). */
28
+ const PTY_READINESS_TIMEOUT_MS = 30_000;
29
+ /** Poll interval when waiting for PTY socket (ms). */
30
+ const PTY_READINESS_POLL_MS = 200;
31
+ /**
32
+ * Runs a PTY session: starts proxies, launches container with PTY-enabled
33
+ * Claude Code, attaches the terminal, and blocks until the session ends.
34
+ */
35
+ export async function runPtySession(options) {
36
+ const { prepareDockerInfrastructure } = await import('./docker-infrastructure.js');
37
+ const sessionId = createSessionId();
38
+ const sessionDir = getSessionDir(sessionId);
39
+ const sandboxDir = getSessionSandboxDir(sessionId);
40
+ const escalationDir = getSessionEscalationDir(sessionId);
41
+ const auditLogPath = getSessionAuditLogPath(sessionId);
42
+ const socketsDir = resolve(sessionDir, 'sockets');
43
+ mkdirSync(sandboxDir, { recursive: true, mode: 0o700 });
44
+ mkdirSync(escalationDir, { recursive: true, mode: 0o700 });
45
+ mkdirSync(socketsDir, { recursive: true, mode: 0o700 });
46
+ // Set up session logging
47
+ const sessionLogPath = getSessionLogPath(sessionId);
48
+ const llmLogPath = getSessionLlmLogPath(sessionId);
49
+ logger.setup({ logFilePath: sessionLogPath });
50
+ logger.info(`PTY session ${sessionId} starting`);
51
+ logger.info(`Sandbox: ${sandboxDir}`);
52
+ logger.info(`Escalation dir: ${escalationDir}`);
53
+ logger.info(`LLM log: ${llmLogPath}`);
54
+ // Patch config for this session
55
+ const sessionConfig = {
56
+ ...options.config,
57
+ allowedDirectory: sandboxDir,
58
+ auditLogPath,
59
+ escalationDir,
60
+ sessionLogPath,
61
+ llmLogPath,
62
+ mcpServers: JSON.parse(JSON.stringify(options.config.mcpServers)),
63
+ };
64
+ const initSpinner = ora({
65
+ text: `Initializing PTY session (${options.mode.agent})...`,
66
+ stream: process.stderr,
67
+ discardStdin: false,
68
+ }).start();
69
+ let containerId = null;
70
+ let sidecarContainerId = null;
71
+ let escalationFileWatcher = null;
72
+ let registrationPath = null;
73
+ let shutdownSpinner = null;
74
+ // Terminal safety: ensure raw mode is restored on any exit
75
+ const restoreTerminal = () => {
76
+ try {
77
+ if (process.stdin.isTTY && process.stdin.isRaw) {
78
+ process.stdin.setRawMode(false);
79
+ process.stdin.pause();
80
+ }
81
+ }
82
+ catch {
83
+ /* best effort */
84
+ }
85
+ };
86
+ process.on('exit', restoreTerminal);
87
+ // SIGTERM triggers graceful shutdown by aborting the PTY connection.
88
+ // This causes attachPty() to resolve, which then falls through to the
89
+ // finally block for full async cleanup (containers, proxies, files).
90
+ const shutdownController = new AbortController();
91
+ const handleSigterm = () => {
92
+ shutdownController.abort();
93
+ };
94
+ process.on('SIGTERM', handleSigterm);
95
+ // Infra variables set inside try, used in finally for cleanup
96
+ let proxy = null;
97
+ let mitmProxy = null;
98
+ let docker = null;
99
+ let useTcp = false;
100
+ try {
101
+ const infra = await prepareDockerInfrastructure(sessionConfig, options.mode, sessionDir, sandboxDir, escalationDir, auditLogPath, sessionId);
102
+ ({ docker, proxy, mitmProxy, useTcp } = infra);
103
+ const { adapter, fakeKeys, orientationDir, systemPrompt, image, mitmAddr } = infra;
104
+ // Validate adapter supports PTY mode
105
+ if (!adapter.buildPtyCommand) {
106
+ throw new Error(`Agent ${adapter.id} does not support PTY mode.`);
107
+ }
108
+ // Write system prompt to file for shell-injection-safe PTY command
109
+ writeFileSync(resolve(orientationDir, 'system-prompt.txt'), systemPrompt);
110
+ // Determine PTY connection target
111
+ const ptySockPath = useTcp ? undefined : `/run/ironcurtain/${PTY_SOCK_NAME}`;
112
+ const ptyPort = useTcp ? DEFAULT_PTY_PORT : undefined;
113
+ // Build the PTY command
114
+ const ptyCommand = adapter.buildPtyCommand(systemPrompt, ptySockPath, ptyPort);
115
+ // Build container configuration
116
+ const shortId = sessionId.substring(0, 12);
117
+ const { INTERNAL_NETWORK_NAME, INTERNAL_NETWORK_SUBNET, INTERNAL_NETWORK_GATEWAY } = await import('./platform.js');
118
+ const { quote } = await import('shell-quote');
119
+ let env;
120
+ let network;
121
+ let mounts;
122
+ let extraHosts;
123
+ if (useTcp && proxy.port !== undefined && mitmAddr.port !== undefined) {
124
+ // macOS TCP mode
125
+ const mcpPort = proxy.port;
126
+ const mitmPort = mitmAddr.port;
127
+ env = {
128
+ ...adapter.buildEnv(sessionConfig, fakeKeys),
129
+ HTTPS_PROXY: `http://host.docker.internal:${mitmPort}`,
130
+ HTTP_PROXY: `http://host.docker.internal:${mitmPort}`,
131
+ };
132
+ await docker.createNetwork(INTERNAL_NETWORK_NAME, {
133
+ internal: true,
134
+ subnet: INTERNAL_NETWORK_SUBNET,
135
+ gateway: INTERNAL_NETWORK_GATEWAY,
136
+ });
137
+ network = INTERNAL_NETWORK_NAME;
138
+ const socatImage = 'alpine/socat';
139
+ if (!(await docker.imageExists(socatImage))) {
140
+ logger.info(`Pulling ${socatImage}...`);
141
+ await docker.pullImage(socatImage);
142
+ }
143
+ // Create socat sidecar with PTY port forwarding
144
+ const sidecarName = `ironcurtain-sidecar-${shortId}`;
145
+ const ptyPortNum = ptyPort ?? DEFAULT_PTY_PORT;
146
+ sidecarContainerId = await docker.create({
147
+ image: socatImage,
148
+ name: sidecarName,
149
+ network: 'bridge',
150
+ mounts: [],
151
+ env: {},
152
+ entrypoint: '/bin/sh',
153
+ command: [
154
+ '-c',
155
+ quote(['socat', `TCP-LISTEN:${mcpPort},fork,reuseaddr`, `TCP:host.docker.internal:${mcpPort}`]) +
156
+ ' & ' +
157
+ quote(['socat', `TCP-LISTEN:${mitmPort},fork,reuseaddr`, `TCP:host.docker.internal:${mitmPort}`]) +
158
+ ' & ' +
159
+ quote(['socat', `TCP-LISTEN:${ptyPortNum},fork,reuseaddr`, `TCP:host.docker.internal:${ptyPortNum}`]) +
160
+ ' & wait',
161
+ ],
162
+ });
163
+ await docker.start(sidecarContainerId);
164
+ await docker.connectNetwork(INTERNAL_NETWORK_NAME, sidecarContainerId);
165
+ const sidecarIp = await docker.getContainerIp(sidecarContainerId, INTERNAL_NETWORK_NAME);
166
+ extraHosts = [`host.docker.internal:${sidecarIp}`];
167
+ mounts = [
168
+ { source: sandboxDir, target: CONTAINER_WORKSPACE_DIR, readonly: false },
169
+ { source: orientationDir, target: '/etc/ironcurtain', readonly: true },
170
+ ];
171
+ }
172
+ else {
173
+ // Linux UDS mode
174
+ env = {
175
+ ...adapter.buildEnv(sessionConfig, fakeKeys),
176
+ HTTPS_PROXY: 'http://127.0.0.1:18080',
177
+ HTTP_PROXY: 'http://127.0.0.1:18080',
178
+ };
179
+ network = 'none';
180
+ mounts = [
181
+ { source: sandboxDir, target: CONTAINER_WORKSPACE_DIR, readonly: false },
182
+ { source: socketsDir, target: '/run/ironcurtain', readonly: false },
183
+ { source: orientationDir, target: '/etc/ironcurtain', readonly: true },
184
+ ];
185
+ }
186
+ // Pass initial terminal size so start-claude.sh can set PTY dimensions
187
+ // before Claude starts, eliminating the resize race condition.
188
+ const { columns, rows } = process.stdout;
189
+ if (columns)
190
+ env.IRONCURTAIN_INITIAL_COLS = String(columns);
191
+ if (rows)
192
+ env.IRONCURTAIN_INITIAL_ROWS = String(rows);
193
+ // Create and start container with PTY command and TTY
194
+ containerId = await docker.create({
195
+ image,
196
+ name: `ironcurtain-pty-${shortId}`,
197
+ network,
198
+ mounts,
199
+ env,
200
+ command: ptyCommand,
201
+ sessionLabel: sessionId,
202
+ resources: { memoryMb: 4096, cpus: 2 },
203
+ extraHosts,
204
+ tty: true,
205
+ });
206
+ await docker.start(containerId);
207
+ logger.info(`PTY container started: ${containerId.substring(0, 12)}`);
208
+ // Write session registration for the escalation listener
209
+ registrationPath = writeRegistration(sessionId, escalationDir, adapter.displayName);
210
+ // Start escalation file watcher (emits BEL to alert user)
211
+ escalationFileWatcher = createEscalationWatcher(escalationDir, {
212
+ onEscalation: () => {
213
+ process.stderr.write('\x07'); // BEL character
214
+ },
215
+ onEscalationExpired: () => { },
216
+ });
217
+ escalationFileWatcher.start();
218
+ // Wait for PTY socket readiness
219
+ const ptyTarget = useTcp
220
+ ? { host: 'localhost', port: ptyPort ?? DEFAULT_PTY_PORT }
221
+ : resolve(socketsDir, PTY_SOCK_NAME);
222
+ await waitForPtyReady(ptyTarget);
223
+ initSpinner.succeed(chalk.dim('PTY session ready'));
224
+ process.stderr.write('\n');
225
+ // Attach terminal via Node.js PTY proxy
226
+ const exitCode = await attachPty({
227
+ target: ptyTarget,
228
+ containerId,
229
+ signal: shutdownController.signal,
230
+ });
231
+ // PTY disconnected -- restore terminal and show shutdown progress
232
+ restoreTerminal();
233
+ process.stderr.write('\n');
234
+ shutdownSpinner = ora({
235
+ text: 'Shutting down PTY session...',
236
+ stream: process.stderr,
237
+ discardStdin: false,
238
+ }).start();
239
+ if (exitCode !== 0) {
240
+ process.stderr.write(chalk.yellow(`PTY session exited with code ${exitCode}\n`));
241
+ }
242
+ }
243
+ finally {
244
+ // Stop spinner if still running (e.g. error during setup)
245
+ if (initSpinner.isSpinning) {
246
+ initSpinner.fail(chalk.red('PTY session failed'));
247
+ }
248
+ restoreTerminal();
249
+ process.off('exit', restoreTerminal);
250
+ process.off('SIGTERM', handleSigterm);
251
+ // Stop escalation watcher
252
+ escalationFileWatcher?.stop();
253
+ // Delete registration file
254
+ if (registrationPath) {
255
+ try {
256
+ unlinkSync(registrationPath);
257
+ }
258
+ catch {
259
+ /* best effort */
260
+ }
261
+ }
262
+ // Stop and remove containers
263
+ if (docker && containerId) {
264
+ await docker.stop(containerId).catch(() => { });
265
+ await docker.remove(containerId).catch(() => { });
266
+ }
267
+ if (docker && sidecarContainerId) {
268
+ await docker.stop(sidecarContainerId).catch(() => { });
269
+ await docker.remove(sidecarContainerId).catch(() => { });
270
+ }
271
+ // Remove internal network if used
272
+ if (docker && useTcp) {
273
+ const { INTERNAL_NETWORK_NAME } = await import('./platform.js');
274
+ await docker.removeNetwork(INTERNAL_NETWORK_NAME).catch(() => { });
275
+ }
276
+ // Stop proxies
277
+ await mitmProxy?.stop().catch(() => { });
278
+ await proxy?.stop().catch(() => { });
279
+ logger.info(`PTY session ${sessionId} ended`);
280
+ logger.teardown();
281
+ // shutdownSpinner is declared inside try but accessible here via closure
282
+ shutdownSpinner?.succeed(chalk.dim('PTY session ended'));
283
+ }
284
+ }
285
+ /** Creates a net.Socket connection to the PTY target (UDS or TCP). */
286
+ function connectToTarget(target) {
287
+ if (typeof target === 'string') {
288
+ return createConnection({ path: target });
289
+ }
290
+ return createConnection({ host: target.host, port: target.port });
291
+ }
292
+ /**
293
+ * Attaches the user's terminal to the container PTY via a Node.js socket.
294
+ * Returns a promise that resolves with 0 on normal close, 1 on error.
295
+ */
296
+ function attachPty(options) {
297
+ const conn = connectToTarget(options.target);
298
+ const { stdin, stdout } = process;
299
+ return new Promise((resolvePromise) => {
300
+ let resolved = false;
301
+ const settle = (code) => {
302
+ if (resolved)
303
+ return;
304
+ resolved = true;
305
+ resolvePromise(code);
306
+ };
307
+ conn.once('connect', () => {
308
+ // Put terminal in raw mode
309
+ if (stdin.isTTY) {
310
+ stdin.setRawMode(true);
311
+ }
312
+ stdin.resume();
313
+ // SIGWINCH: forward terminal resize to container PTY.
314
+ // verifyAbort cancels the background verify loop on first user resize
315
+ // so it doesn't fight with the new size.
316
+ const verifyAbort = new AbortController();
317
+ let isFirstResize = true;
318
+ const onResize = () => {
319
+ const { columns, rows } = stdout;
320
+ if (columns && rows) {
321
+ if (!isFirstResize) {
322
+ verifyAbort.abort();
323
+ }
324
+ isFirstResize = false;
325
+ execFile('docker', ['exec', options.containerId, '/etc/ironcurtain/resize-pty.sh', String(columns), String(rows)], { timeout: 5000 }, (err, _stdout, stderr) => {
326
+ if (err) {
327
+ logger.warn(`resize-pty.sh failed: ${err.message}`);
328
+ if (stderr) {
329
+ logger.warn(`resize-pty.sh stderr: ${stderr.trim()}`);
330
+ }
331
+ }
332
+ });
333
+ }
334
+ };
335
+ stdout.on('resize', onResize);
336
+ // Send initial size
337
+ onResize();
338
+ // Background verify+retry to ensure the initial resize took effect.
339
+ // Fire-and-forget -- does not block the PTY proxy.
340
+ // Canceled via verifyAbort when the user resizes the terminal.
341
+ if (stdout.columns && stdout.rows) {
342
+ void verifyInitialPtySize(options.containerId, stdout.columns, stdout.rows, verifyAbort.signal);
343
+ }
344
+ // Host -> Container
345
+ // Ctrl-\ (0x1c) is intercepted as an emergency exit since raw mode
346
+ // disables normal signal generation for SIGQUIT.
347
+ const CTRL_BACKSLASH = 0x1c;
348
+ const onData = (data) => {
349
+ if (data.length === 1 && data[0] === CTRL_BACKSLASH) {
350
+ cleanup();
351
+ conn.destroy();
352
+ settle(0);
353
+ return;
354
+ }
355
+ conn.write(data);
356
+ };
357
+ stdin.on('data', onData);
358
+ // Container -> Host (untrusted output, displayed directly)
359
+ conn.pipe(stdout);
360
+ // Use function declarations (hoisted) so cleanup and onAbort can
361
+ // reference each other without temporal dead zone issues.
362
+ function cleanup() {
363
+ stdout.removeListener('resize', onResize);
364
+ stdin.removeListener('data', onData);
365
+ conn.unpipe(stdout);
366
+ stdin.pause();
367
+ verifyAbort.abort();
368
+ options.signal?.removeEventListener('abort', onAbort);
369
+ }
370
+ function onAbort() {
371
+ cleanup();
372
+ conn.destroy();
373
+ settle(0);
374
+ }
375
+ if (options.signal?.aborted) {
376
+ onAbort();
377
+ return;
378
+ }
379
+ options.signal?.addEventListener('abort', onAbort, { once: true });
380
+ conn.once('close', () => {
381
+ cleanup();
382
+ settle(0);
383
+ });
384
+ conn.once('error', () => {
385
+ cleanup();
386
+ settle(1);
387
+ });
388
+ });
389
+ conn.once('error', () => {
390
+ settle(1);
391
+ });
392
+ });
393
+ }
394
+ // --- PTY size verification ---
395
+ /** Maximum retries for initial PTY size verification. */
396
+ const PTY_SIZE_VERIFY_RETRIES = 5;
397
+ /** Interval between PTY size verification attempts (ms). */
398
+ const PTY_SIZE_VERIFY_INTERVAL_MS = 1_000;
399
+ /** Initial delay before first verification attempt (ms). */
400
+ const PTY_SIZE_VERIFY_INITIAL_DELAY_MS = 500;
401
+ /**
402
+ * Runs check-pty-size.sh and returns { rows, cols } or null on failure.
403
+ */
404
+ function checkPtySize(containerId) {
405
+ return new Promise((resolve) => {
406
+ execFile('docker', ['exec', containerId, '/etc/ironcurtain/check-pty-size.sh'], { timeout: 5000 }, (err, stdout) => {
407
+ if (err) {
408
+ resolve(null);
409
+ return;
410
+ }
411
+ const parts = stdout.trim().split(/\s+/);
412
+ if (parts.length >= 2) {
413
+ const rows = parseInt(parts[0], 10);
414
+ const cols = parseInt(parts[1], 10);
415
+ if (!isNaN(rows) && !isNaN(cols) && rows > 0 && cols > 0) {
416
+ resolve({ rows, cols });
417
+ return;
418
+ }
419
+ }
420
+ resolve(null);
421
+ });
422
+ });
423
+ }
424
+ /**
425
+ * Background verify+retry loop for initial PTY resize.
426
+ * Non-blocking (fire-and-forget). Aborted when a user resize occurs so it
427
+ * does not fight with legitimate SIGWINCH-driven resizes.
428
+ */
429
+ async function verifyInitialPtySize(containerId, expectedCols, expectedRows, signal) {
430
+ await new Promise((r) => setTimeout(r, PTY_SIZE_VERIFY_INITIAL_DELAY_MS));
431
+ for (let attempt = 0; attempt < PTY_SIZE_VERIFY_RETRIES; attempt++) {
432
+ if (signal?.aborted)
433
+ return;
434
+ const size = await checkPtySize(containerId);
435
+ if (size && size.cols === expectedCols && size.rows === expectedRows) {
436
+ return; // PTY size matches
437
+ }
438
+ if (signal?.aborted)
439
+ return;
440
+ // Mismatch or check failed -- try resizing
441
+ await new Promise((resolve) => {
442
+ execFile('docker', ['exec', containerId, '/etc/ironcurtain/resize-pty.sh', String(expectedCols), String(expectedRows)], { timeout: 5000 }, () => resolve());
443
+ });
444
+ // Wait before rechecking
445
+ await new Promise((r) => setTimeout(r, PTY_SIZE_VERIFY_INTERVAL_MS));
446
+ }
447
+ if (signal?.aborted)
448
+ return;
449
+ // Final check
450
+ const finalSize = await checkPtySize(containerId);
451
+ if (!finalSize || finalSize.cols !== expectedCols || finalSize.rows !== expectedRows) {
452
+ logger.warn(`PTY size verification failed after ${PTY_SIZE_VERIFY_RETRIES} retries ` +
453
+ `(expected ${expectedCols}x${expectedRows}, got ${finalSize ? `${finalSize.cols}x${finalSize.rows}` : 'unknown'})`);
454
+ }
455
+ }
456
+ // --- Readiness polling ---
457
+ /**
458
+ * Waits for the PTY socket/port to become connectable.
459
+ */
460
+ async function waitForPtyReady(target) {
461
+ const deadline = Date.now() + PTY_READINESS_TIMEOUT_MS;
462
+ while (Date.now() < deadline) {
463
+ const connected = await tryConnect(target);
464
+ if (connected)
465
+ return;
466
+ await new Promise((r) => setTimeout(r, PTY_READINESS_POLL_MS));
467
+ }
468
+ throw new Error(`PTY socket did not become ready within ${PTY_READINESS_TIMEOUT_MS / 1000}s`);
469
+ }
470
+ /**
471
+ * Tries to connect to a target. Returns true if the connection succeeds.
472
+ */
473
+ function tryConnect(target) {
474
+ return new Promise((resolve) => {
475
+ const conn = connectToTarget(target);
476
+ const timer = setTimeout(() => {
477
+ conn.destroy();
478
+ resolve(false);
479
+ }, 1000);
480
+ conn.on('connect', () => {
481
+ clearTimeout(timer);
482
+ conn.destroy();
483
+ resolve(true);
484
+ });
485
+ conn.on('error', () => {
486
+ clearTimeout(timer);
487
+ resolve(false);
488
+ });
489
+ });
490
+ }
491
+ // --- Registration ---
492
+ /**
493
+ * Writes a PTY session registration file to the registry directory.
494
+ * Returns the absolute path of the registration file.
495
+ */
496
+ function writeRegistration(sessionId, escalationDir, adapterDisplayName) {
497
+ const registryDir = getPtyRegistryDir();
498
+ mkdirSync(registryDir, { recursive: true, mode: 0o700 });
499
+ const registration = {
500
+ sessionId,
501
+ escalationDir,
502
+ label: `${adapterDisplayName} (interactive)`,
503
+ startedAt: new Date().toISOString(),
504
+ pid: process.pid,
505
+ };
506
+ const registrationPath = resolve(registryDir, `session-${sessionId}.json`);
507
+ atomicWriteJsonSync(registrationPath, registration);
508
+ return registrationPath;
509
+ }
510
+ //# sourceMappingURL=pty-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-session.js","sourceRoot":"","sources":["../../src/docker/pty-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Types for PTY session management and the escalation listener.
3
+ */
4
+ /** Registration file written by PTY sessions for the escalation listener. */
5
+ export interface PtySessionRegistration {
6
+ /** Unique session identifier (SessionId). */
7
+ readonly sessionId: string;
8
+ /** Absolute path to the session's escalation directory. */
9
+ readonly escalationDir: string;
10
+ /** Human-readable label for TUI display. */
11
+ readonly label: string;
12
+ /** ISO 8601 timestamp when the session started. */
13
+ readonly startedAt: string;
14
+ /** PID of the ironcurtain process managing this session. */
15
+ readonly pid: number;
16
+ }
17
+ /** Well-known directory for PTY session registration files. */
18
+ export declare const PTY_REGISTRY_DIR_NAME = "pty-registry";
19
+ /** Lock file name for single-instance enforcement. */
20
+ export declare const LISTENER_LOCK_FILE = "escalation-listener.lock";
21
+ /** PTY socket filename (Linux UDS mode). */
22
+ export declare const PTY_SOCK_NAME = "pty.sock";
23
+ /** Default PTY port inside the container (macOS TCP mode only). */
24
+ export declare const DEFAULT_PTY_PORT = 19000;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Types for PTY session management and the escalation listener.
3
+ */
4
+ /** Well-known directory for PTY session registration files. */
5
+ export const PTY_REGISTRY_DIR_NAME = 'pty-registry';
6
+ /** Lock file name for single-instance enforcement. */
7
+ export const LISTENER_LOCK_FILE = 'escalation-listener.lock';
8
+ /** PTY socket filename (Linux UDS mode). */
9
+ export const PTY_SOCK_NAME = 'pty.sock';
10
+ /** Default PTY port inside the container (macOS TCP mode only). */
11
+ export const DEFAULT_PTY_PORT = 19000;
12
+ //# sourceMappingURL=pty-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-types.js","sourceRoot":"","sources":["../../src/docker/pty-types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgBH,+DAA+D;AAC/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAEpD,sDAAsD;AACtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,0BAA0B,CAAC;AAE7D,4CAA4C;AAC5C,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;AAExC,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC"}
@@ -57,6 +57,12 @@ export interface DockerContainerConfig {
57
57
  * must NEVER set this field.
58
58
  */
59
59
  readonly capAdd?: readonly string[];
60
+ /**
61
+ * Allocate a pseudo-TTY for the container (-t flag).
62
+ * Required for PTY mode where the container runs an interactive process.
63
+ * Optional. Defaults to false (no TTY allocated).
64
+ */
65
+ readonly tty?: boolean;
60
66
  }
61
67
  /** A volume mount for a Docker container. */
62
68
  export interface DockerMount {
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Shared escalation watcher for polling escalation directories.
3
+ *
4
+ * Pure data module -- no I/O presentation. Consumers (DockerAgentSession,
5
+ * EscalationListener) handle display. Polls a session's escalation
6
+ * directory for new request files and handles resolution via response files.
7
+ */
8
+ import type { EscalationRequest } from '../session/types.js';
9
+ /** Events emitted by the escalation watcher. */
10
+ export interface EscalationWatcherEvents {
11
+ /** A new escalation request was detected. */
12
+ onEscalation: (request: EscalationRequest) => void;
13
+ /** A pending escalation expired (proxy timed out and cleaned up files). */
14
+ onEscalationExpired: (escalationId: string) => void;
15
+ }
16
+ export interface EscalationWatcher {
17
+ /** Start polling the escalation directory. */
18
+ start(): void;
19
+ /** Stop polling. */
20
+ stop(): void;
21
+ /** Returns the currently pending escalation, if any. */
22
+ getPending(): EscalationRequest | undefined;
23
+ /**
24
+ * Resolves a pending escalation by writing the response file.
25
+ * Returns true if the resolution was accepted (request file still exists),
26
+ * or false if the escalation had already expired.
27
+ *
28
+ * @throws {Error} if no escalation with this ID is pending
29
+ */
30
+ resolve(escalationId: string, decision: 'approved' | 'denied'): boolean;
31
+ }
32
+ export interface EscalationWatcherOptions {
33
+ /** Poll interval in ms. Default: 300. */
34
+ pollIntervalMs?: number;
35
+ }
36
+ /**
37
+ * Atomically writes a JSON file using write-to-temp-then-rename.
38
+ * Prevents partial reads by other processes polling the same directory.
39
+ */
40
+ export declare function atomicWriteJsonSync(filePath: string, data: unknown): void;
41
+ /**
42
+ * Creates an escalation watcher for a single session's escalation directory.
43
+ */
44
+ export declare function createEscalationWatcher(escalationDir: string, events: EscalationWatcherEvents, options?: EscalationWatcherOptions): EscalationWatcher;