@provos/ironcurtain 0.4.0 → 0.5.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 (161) 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/index.js +6 -0
  12. package/dist/config/index.js.map +1 -1
  13. package/dist/config/mcp-servers.json +13 -0
  14. package/dist/config/paths.d.ts +31 -0
  15. package/dist/config/paths.js +52 -2
  16. package/dist/config/paths.js.map +1 -1
  17. package/dist/config/types.d.ts +10 -0
  18. package/dist/config/user-config.d.ts +21 -3
  19. package/dist/config/user-config.js +34 -3
  20. package/dist/config/user-config.js.map +1 -1
  21. package/dist/docker/adapters/claude-code.d.ts +4 -0
  22. package/dist/docker/adapters/claude-code.js +96 -37
  23. package/dist/docker/adapters/claude-code.js.map +1 -1
  24. package/dist/docker/agent-adapter.d.ts +22 -13
  25. package/dist/docker/code-mode-proxy.d.ts +34 -0
  26. package/dist/docker/code-mode-proxy.js +137 -0
  27. package/dist/docker/code-mode-proxy.js.map +1 -0
  28. package/dist/docker/docker-agent-session.d.ts +22 -14
  29. package/dist/docker/docker-agent-session.js +144 -117
  30. package/dist/docker/docker-agent-session.js.map +1 -1
  31. package/dist/docker/docker-infrastructure.d.ts +51 -0
  32. package/dist/docker/docker-infrastructure.js +261 -0
  33. package/dist/docker/docker-infrastructure.js.map +1 -0
  34. package/dist/docker/docker-manager.js +27 -0
  35. package/dist/docker/docker-manager.js.map +1 -1
  36. package/dist/docker/mitm-proxy.js +4 -0
  37. package/dist/docker/mitm-proxy.js.map +1 -1
  38. package/dist/docker/oauth-credentials.d.ts +81 -0
  39. package/dist/docker/oauth-credentials.js +178 -0
  40. package/dist/docker/oauth-credentials.js.map +1 -0
  41. package/dist/docker/orientation.d.ts +3 -2
  42. package/dist/docker/orientation.js +4 -4
  43. package/dist/docker/orientation.js.map +1 -1
  44. package/dist/docker/provider-config.d.ts +3 -0
  45. package/dist/docker/provider-config.js +28 -0
  46. package/dist/docker/provider-config.js.map +1 -1
  47. package/dist/docker/pty-session.d.ts +27 -0
  48. package/dist/docker/pty-session.js +420 -0
  49. package/dist/docker/pty-session.js.map +1 -0
  50. package/dist/docker/pty-types.d.ts +24 -0
  51. package/dist/docker/pty-types.js +12 -0
  52. package/dist/docker/pty-types.js.map +1 -0
  53. package/dist/docker/types.d.ts +18 -2
  54. package/dist/escalation/escalation-watcher.d.ts +44 -0
  55. package/dist/escalation/escalation-watcher.js +92 -0
  56. package/dist/escalation/escalation-watcher.js.map +1 -0
  57. package/dist/escalation/listener-command.d.ts +10 -0
  58. package/dist/escalation/listener-command.js +407 -0
  59. package/dist/escalation/listener-command.js.map +1 -0
  60. package/dist/escalation/listener-state.d.ts +49 -0
  61. package/dist/escalation/listener-state.js +104 -0
  62. package/dist/escalation/listener-state.js.map +1 -0
  63. package/dist/escalation/session-registry.d.ts +17 -0
  64. package/dist/escalation/session-registry.js +98 -0
  65. package/dist/escalation/session-registry.js.map +1 -0
  66. package/dist/index.js +15 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/logger.js +2 -3
  69. package/dist/logger.js.map +1 -1
  70. package/dist/pipeline/annotate.js +35 -15
  71. package/dist/pipeline/annotate.js.map +1 -1
  72. package/dist/pipeline/constitution-customizer.d.ts +2 -1
  73. package/dist/pipeline/constitution-customizer.js +36 -3
  74. package/dist/pipeline/constitution-customizer.js.map +1 -1
  75. package/dist/pipeline/github-identity.d.ts +38 -0
  76. package/dist/pipeline/github-identity.js +64 -0
  77. package/dist/pipeline/github-identity.js.map +1 -0
  78. package/dist/pipeline/handwritten-scenarios.js +34 -0
  79. package/dist/pipeline/handwritten-scenarios.js.map +1 -1
  80. package/dist/sandbox/index.d.ts +25 -1
  81. package/dist/sandbox/index.js +90 -12
  82. package/dist/sandbox/index.js.map +1 -1
  83. package/dist/servers/fetch-server.d.ts +6 -1
  84. package/dist/servers/fetch-server.js +26 -14
  85. package/dist/servers/fetch-server.js.map +1 -1
  86. package/dist/session/agent-session.js +9 -5
  87. package/dist/session/agent-session.js.map +1 -1
  88. package/dist/session/base-transport.d.ts +19 -0
  89. package/dist/session/base-transport.js +36 -0
  90. package/dist/session/base-transport.js.map +1 -0
  91. package/dist/session/cli-transport.d.ts +3 -3
  92. package/dist/session/cli-transport.js +7 -4
  93. package/dist/session/cli-transport.js.map +1 -1
  94. package/dist/session/index.js +24 -106
  95. package/dist/session/index.js.map +1 -1
  96. package/dist/session/interaction-log.d.ts +13 -0
  97. package/dist/session/interaction-log.js +28 -0
  98. package/dist/session/interaction-log.js.map +1 -0
  99. package/dist/session/preflight.d.ts +3 -0
  100. package/dist/session/preflight.js +45 -18
  101. package/dist/session/preflight.js.map +1 -1
  102. package/dist/session/prompts.d.ts +9 -3
  103. package/dist/session/prompts.js +28 -10
  104. package/dist/session/prompts.js.map +1 -1
  105. package/dist/session/types.d.ts +2 -0
  106. package/dist/signal/bot-command.js +5 -0
  107. package/dist/signal/bot-command.js.map +1 -1
  108. package/dist/signal/format.d.ts +21 -1
  109. package/dist/signal/format.js +41 -3
  110. package/dist/signal/format.js.map +1 -1
  111. package/dist/signal/signal-bot-daemon.d.ts +53 -18
  112. package/dist/signal/signal-bot-daemon.js +344 -106
  113. package/dist/signal/signal-bot-daemon.js.map +1 -1
  114. package/dist/signal/signal-config.d.ts +4 -0
  115. package/dist/signal/signal-config.js +2 -0
  116. package/dist/signal/signal-config.js.map +1 -1
  117. package/dist/signal/signal-transport.d.ts +13 -7
  118. package/dist/signal/signal-transport.js +36 -12
  119. package/dist/signal/signal-transport.js.map +1 -1
  120. package/dist/trusted-process/audit-log.d.ts +6 -1
  121. package/dist/trusted-process/audit-log.js +22 -2
  122. package/dist/trusted-process/audit-log.js.map +1 -1
  123. package/dist/trusted-process/audit-redactor.d.ts +25 -0
  124. package/dist/trusted-process/audit-redactor.js +121 -0
  125. package/dist/trusted-process/audit-redactor.js.map +1 -0
  126. package/dist/trusted-process/escalation.d.ts +1 -1
  127. package/dist/trusted-process/escalation.js +6 -1
  128. package/dist/trusted-process/escalation.js.map +1 -1
  129. package/dist/trusted-process/index.d.ts +2 -1
  130. package/dist/trusted-process/index.js +24 -6
  131. package/dist/trusted-process/index.js.map +1 -1
  132. package/dist/trusted-process/mcp-client-manager.js +14 -2
  133. package/dist/trusted-process/mcp-client-manager.js.map +1 -1
  134. package/dist/trusted-process/mcp-error-utils.d.ts +11 -0
  135. package/dist/trusted-process/mcp-error-utils.js +50 -0
  136. package/dist/trusted-process/mcp-error-utils.js.map +1 -0
  137. package/dist/trusted-process/mcp-proxy-server.d.ts +115 -1
  138. package/dist/trusted-process/mcp-proxy-server.js +318 -267
  139. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  140. package/dist/trusted-process/policy-engine.d.ts +3 -1
  141. package/dist/trusted-process/policy-engine.js +17 -6
  142. package/dist/trusted-process/policy-engine.js.map +1 -1
  143. package/dist/trusted-process/sandbox-integration.d.ts +16 -4
  144. package/dist/trusted-process/sandbox-integration.js +14 -8
  145. package/dist/trusted-process/sandbox-integration.js.map +1 -1
  146. package/dist/trusted-process/server-context.d.ts +21 -0
  147. package/dist/trusted-process/server-context.js +42 -0
  148. package/dist/trusted-process/server-context.js.map +1 -0
  149. package/dist/types/argument-roles.d.ts +12 -2
  150. package/dist/types/argument-roles.js +37 -4
  151. package/dist/types/argument-roles.js.map +1 -1
  152. package/docker/Dockerfile.claude-code +8 -3
  153. package/docker/entrypoint-claude-code.sh +64 -4
  154. package/package.json +19 -9
  155. package/src/config/constitution-user-base.md +2 -0
  156. package/src/config/generated/compiled-policy.json +199 -72
  157. package/src/config/generated/tool-annotations.json +1018 -36
  158. package/src/config/mcp-servers.json +13 -0
  159. package/dist/docker/managed-proxy.d.ts +0 -31
  160. package/dist/docker/managed-proxy.js +0 -265
  161. package/dist/docker/managed-proxy.js.map +0 -1
@@ -12,8 +12,11 @@ export declare const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
12
12
  * Formats an escalation request as a styled text banner.
13
13
  * Includes tool name, arguments, reason, and instructions
14
14
  * for the user to reply "approve" or "deny".
15
+ *
16
+ * When sessionLabel is provided, includes `[#N]` in the header
17
+ * so the user knows which session is escalating.
15
18
  */
16
- export declare function formatEscalationBanner(request: EscalationRequest): string;
19
+ export declare function formatEscalationBanner(request: EscalationRequest, sessionLabel?: number): string;
17
20
  /**
18
21
  * Formats budget status for the /budget command.
19
22
  * Shows current turn consumption and session totals.
@@ -29,3 +32,20 @@ export declare function formatBudgetSummary(status: BudgetStatus): string;
29
32
  * then single newlines, then at the hard limit.
30
33
  */
31
34
  export declare function splitMessage(text: string, maxLength: number): string[];
35
+ /**
36
+ * Information about a managed session for display purposes.
37
+ */
38
+ export interface SessionListEntry {
39
+ readonly label: number;
40
+ readonly turnCount: number;
41
+ readonly budgetPercent: number;
42
+ }
43
+ /**
44
+ * Formats the /sessions command output.
45
+ * Marks the current session with `>`.
46
+ */
47
+ export declare function formatSessionList(sessions: SessionListEntry[], currentLabel: number | null): string;
48
+ /**
49
+ * Prefixes a message with `[#N]` when multiple sessions are active.
50
+ */
51
+ export declare function prefixWithLabel(text: string, label: number, sessionCount: number): string;
@@ -11,15 +11,31 @@ export const SIGNAL_MAX_MESSAGE_LENGTH = 2000;
11
11
  * Formats an escalation request as a styled text banner.
12
12
  * Includes tool name, arguments, reason, and instructions
13
13
  * for the user to reply "approve" or "deny".
14
+ *
15
+ * When sessionLabel is provided, includes `[#N]` in the header
16
+ * so the user knows which session is escalating.
14
17
  */
15
- export function formatEscalationBanner(request) {
18
+ export function formatEscalationBanner(request, sessionLabel) {
16
19
  const separator = '\u2501'.repeat(30); // box drawing heavy horizontal
17
- const header = '**ESCALATION: Human approval required**';
20
+ const labelTag = sessionLabel != null ? ` [#${sessionLabel}]` : '';
21
+ const header = `**ESCALATION${labelTag}: Human approval required**`;
18
22
  const toolLine = `Tool: \`${request.serverName}/${request.toolName}\``;
19
23
  const argsLine = `Arguments: \`${JSON.stringify(request.arguments)}\``;
24
+ const contextLines = request.context ? Object.entries(request.context).map(([k, v]) => `${k}: \`${v}\``) : [];
20
25
  const reasonLine = `Reason: *${request.reason}*`;
21
26
  const instructions = '**Reply "approve" or "deny"**';
22
- return [separator, header, separator, toolLine, argsLine, reasonLine, separator, instructions, separator].join('\n');
27
+ return [
28
+ separator,
29
+ header,
30
+ separator,
31
+ toolLine,
32
+ argsLine,
33
+ ...contextLines,
34
+ reasonLine,
35
+ separator,
36
+ instructions,
37
+ separator,
38
+ ].join('\n');
23
39
  }
24
40
  /**
25
41
  * Formats budget status for the /budget command.
@@ -90,6 +106,28 @@ export function splitMessage(text, maxLength) {
90
106
  }
91
107
  return chunks;
92
108
  }
109
+ /**
110
+ * Formats the /sessions command output.
111
+ * Marks the current session with `>`.
112
+ */
113
+ export function formatSessionList(sessions, currentLabel) {
114
+ if (sessions.length === 0)
115
+ return 'No active sessions.';
116
+ const lines = ['**Active sessions:**'];
117
+ for (const s of sessions) {
118
+ const marker = s.label === currentLabel ? '>' : ' ';
119
+ lines.push(`${marker} #${s.label} turns: ${s.turnCount} budget: ${s.budgetPercent}%`);
120
+ }
121
+ return lines.join('\n');
122
+ }
123
+ /**
124
+ * Prefixes a message with `[#N]` when multiple sessions are active.
125
+ */
126
+ export function prefixWithLabel(text, label, sessionCount) {
127
+ if (sessionCount <= 1)
128
+ return text;
129
+ return `[#${label}] ${text}`;
130
+ }
93
131
  // --- Private helpers ---
94
132
  function formatBudgetLine(label, current, limit, format) {
95
133
  const currentStr = format(current);
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/signal/format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/signal/format.ts"],"names":[],"mappings":"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"}
@@ -5,9 +5,9 @@
5
5
  * - WebSocket connection to signal-cli-rest-api with reconnect + exponential backoff
6
6
  * - Message routing: authorization, identity verification, escalation replies,
7
7
  * control commands, and session forwarding
8
- * - Session lifecycle: creates transport+session on demand, cleans up on end
8
+ * - Multi-session lifecycle: creates transport+session on demand, cleans up on end
9
9
  * - Identity verification with TTL cache (5 min), fail-closed
10
- * - Escalation state with race prevention
10
+ * - Escalation state with race prevention (per-session)
11
11
  * - Message sending via POST /v2/send with text_mode: "styled"
12
12
  */
13
13
  import { type ResolvedSignalConfig } from './signal-config.js';
@@ -57,23 +57,29 @@ export declare class SignalBotDaemon {
57
57
  private reconnectAttempts;
58
58
  private static readonly MAX_RECONNECT_DELAY_MS;
59
59
  private static readonly BASE_RECONNECT_DELAY_MS;
60
- private activeSession;
61
- private activeTransport;
62
- private messageInFlight;
63
- private pendingEscalationId;
64
- private escalationResolving;
60
+ private sessions;
61
+ private currentLabel;
62
+ private nextLabel;
63
+ private readonly maxConcurrentSessions;
65
64
  private identityLocked;
66
65
  private lastIdentityCheckMs;
67
66
  private recentTimestamps;
67
+ private sessionOpInProgress;
68
68
  private exitResolve;
69
69
  constructor(options: SignalBotDaemonOptions);
70
+ /**
71
+ * Schedules a session-mutating operation (/new, /quit) so that
72
+ * concurrent routeToSession() calls wait for it to complete.
73
+ * Operations are chained to prevent interleaving.
74
+ */
75
+ private scheduleSessionOp;
70
76
  /**
71
77
  * Starts the daemon. Returns a promise that resolves when
72
78
  * shutdown() is called (e.g., SIGTERM/SIGINT).
73
79
  */
74
80
  start(): Promise<void>;
75
81
  /**
76
- * Initiates graceful shutdown. Ends the active session,
82
+ * Initiates graceful shutdown. Ends all active sessions,
77
83
  * closes the WebSocket, and unblocks start().
78
84
  */
79
85
  shutdown(): Promise<void>;
@@ -87,36 +93,54 @@ export declare class SignalBotDaemon {
87
93
  private scheduleReconnect;
88
94
  private handleIncomingMessage;
89
95
  /**
90
- * Routes a user message to the active session. Creates a new
96
+ * Routes a user message to the current session. Creates a new
91
97
  * session if none exists. Handles BudgetExhaustedError by ending
92
98
  * the exhausted session and notifying the user.
99
+ *
100
+ * Supports one-shot `#N` prefix routing: `#2 do something` routes
101
+ * "do something" to session #2 without changing currentLabel.
93
102
  */
94
103
  private routeToSession;
104
+ /**
105
+ * Forwards a message to a specific managed session. Handles
106
+ * in-flight guards, BudgetExhaustedError, and response formatting.
107
+ */
108
+ private forwardToSession;
95
109
  /**
96
110
  * Creates a new session with a fresh SignalSessionTransport.
97
111
  * Follows the same pattern as index.ts: create transport,
98
112
  * wire callbacks, create session, start transport.
113
+ * Returns the label of the new session.
99
114
  */
100
115
  private startNewSession;
101
116
  /**
102
- * Ends the current session and cleans up. Awaits session.close()
103
- * to ensure resources are released (sandbox, MCP connections, etc.).
104
- * Guarded against re-entrance.
117
+ * Ends a specific session by label and cleans up.
118
+ * If it was the current session, auto-switches to the most recent remaining.
119
+ */
120
+ endSession(label: number): Promise<void>;
121
+ /**
122
+ * Convenience method: ends the current session (if any).
105
123
  */
106
124
  endCurrentSession(): Promise<void>;
125
+ /**
126
+ * Auto-switches currentLabel to the highest remaining label (most recent),
127
+ * or null if no sessions remain.
128
+ */
129
+ private autoSwitchCurrent;
107
130
  /**
108
131
  * Checks if the message is an escalation reply.
109
132
  * Accepts: approve, deny, /approve, /deny (case-insensitive).
133
+ * Optionally with a session label: "approve #2", "/approve 2".
110
134
  *
111
- * Race condition prevention: escalationResolving flag prevents
112
- * concurrent replies. pendingEscalationId is cleared in .finally()
113
- * after async resolution completes, not before.
135
+ * Routes to the session with a pending escalation. If multiple
136
+ * sessions have pending escalations and no label is specified,
137
+ * asks for disambiguation.
114
138
  */
115
139
  private handleEscalationReply;
116
140
  /** Called by SignalSessionTransport when the session surfaces an escalation. */
117
- setPendingEscalation(escalationId: string): void;
141
+ setPendingEscalation(label: number, escalationId: string): void;
118
142
  /** Called by SignalSessionTransport when an escalation expires. */
119
- clearPendingEscalation(): void;
143
+ clearPendingEscalation(label: number): void;
120
144
  private handleControlCommand;
121
145
  /**
122
146
  * Checks whether the sender's Signal identity key has changed.
@@ -137,6 +161,17 @@ export declare class SignalBotDaemon {
137
161
  private postMessage;
138
162
  }
139
163
  export declare function parseSignalEnvelope(data: string): SignalEnvelope | null;
140
- /** Normalize a phone number by stripping spaces. */
141
164
  export declare function normalizePhoneNumber(number: string): string;
142
165
  export declare function isAuthorizedSender(envelope: SignalEnvelope, recipientNumber: string): boolean;
166
+ export interface HashPrefixResult {
167
+ /** The session label from the #N prefix, or null if no prefix was found. */
168
+ targetLabel: number | null;
169
+ /** The message text with the #N prefix stripped (or the original text if no prefix). */
170
+ messageText: string;
171
+ }
172
+ /**
173
+ * Parses an optional `#N` prefix from a message for one-shot session routing.
174
+ * Pattern: `#N ` at the start, where N is one or more digits, followed by a space.
175
+ * E.g., `#2 do something` -> { targetLabel: 2, messageText: 'do something' }
176
+ */
177
+ export declare function parseHashPrefix(text: string): HashPrefixResult;