@provos/ironcurtain 0.8.0 → 0.9.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 (207) hide show
  1. package/dist/auth/auth-command.d.ts +15 -0
  2. package/dist/auth/auth-command.js +424 -0
  3. package/dist/auth/auth-command.js.map +1 -0
  4. package/dist/auth/oauth-flow.d.ts +46 -0
  5. package/dist/auth/oauth-flow.js +279 -0
  6. package/dist/auth/oauth-flow.js.map +1 -0
  7. package/dist/auth/oauth-provider.d.ts +55 -0
  8. package/dist/auth/oauth-provider.js +73 -0
  9. package/dist/auth/oauth-provider.js.map +1 -0
  10. package/dist/auth/oauth-registry.d.ts +34 -0
  11. package/dist/auth/oauth-registry.js +69 -0
  12. package/dist/auth/oauth-registry.js.map +1 -0
  13. package/dist/auth/oauth-token-provider.d.ts +52 -0
  14. package/dist/auth/oauth-token-provider.js +159 -0
  15. package/dist/auth/oauth-token-provider.js.map +1 -0
  16. package/dist/auth/oauth-token-store.d.ts +30 -0
  17. package/dist/auth/oauth-token-store.js +93 -0
  18. package/dist/auth/oauth-token-store.js.map +1 -0
  19. package/dist/auth/providers/google-scopes.d.ts +35 -0
  20. package/dist/auth/providers/google-scopes.js +183 -0
  21. package/dist/auth/providers/google-scopes.js.map +1 -0
  22. package/dist/auth/providers/google.d.ts +2 -0
  23. package/dist/auth/providers/google.js +28 -0
  24. package/dist/auth/providers/google.js.map +1 -0
  25. package/dist/cli.js +6 -0
  26. package/dist/cli.js.map +1 -1
  27. package/dist/config/config-command.js +39 -1
  28. package/dist/config/config-command.js.map +1 -1
  29. package/dist/config/constitution-readonly.md +14 -11
  30. package/dist/config/constitution-user-base.md +15 -0
  31. package/dist/config/generated/test-scenarios.json +1 -1
  32. package/dist/config/generated/tool-annotations.json +10617 -296
  33. package/dist/config/generated-readonly/compiled-policy.json +787 -244
  34. package/dist/config/index.d.ts +2 -2
  35. package/dist/config/index.js +8 -0
  36. package/dist/config/index.js.map +1 -1
  37. package/dist/config/mcp-servers.json +23 -0
  38. package/dist/config/paths.d.ts +15 -0
  39. package/dist/config/paths.js +35 -0
  40. package/dist/config/paths.js.map +1 -1
  41. package/dist/config/types.d.ts +8 -0
  42. package/dist/config/user-config.d.ts +2 -0
  43. package/dist/config/user-config.js +2 -0
  44. package/dist/config/user-config.js.map +1 -1
  45. package/dist/cron/headless-transport.d.ts +4 -0
  46. package/dist/cron/headless-transport.js +1 -1
  47. package/dist/cron/headless-transport.js.map +1 -1
  48. package/dist/daemon/ironcurtain-daemon.js +6 -1
  49. package/dist/daemon/ironcurtain-daemon.js.map +1 -1
  50. package/dist/docker/docker-agent-session.d.ts +3 -1
  51. package/dist/docker/docker-agent-session.js +49 -28
  52. package/dist/docker/docker-agent-session.js.map +1 -1
  53. package/dist/docker/docker-infrastructure.js +33 -8
  54. package/dist/docker/docker-infrastructure.js.map +1 -1
  55. package/dist/docker/docker-manager.d.ts +2 -0
  56. package/dist/docker/docker-manager.js +9 -1
  57. package/dist/docker/docker-manager.js.map +1 -1
  58. package/dist/docker/mitm-proxy.d.ts +50 -0
  59. package/dist/docker/mitm-proxy.js +220 -31
  60. package/dist/docker/mitm-proxy.js.map +1 -1
  61. package/dist/docker/platform.d.ts +6 -6
  62. package/dist/docker/platform.js +8 -6
  63. package/dist/docker/platform.js.map +1 -1
  64. package/dist/docker/proxy-tools.d.ts +80 -0
  65. package/dist/docker/proxy-tools.js +248 -0
  66. package/dist/docker/proxy-tools.js.map +1 -0
  67. package/dist/docker/pty-session.js +48 -29
  68. package/dist/docker/pty-session.js.map +1 -1
  69. package/dist/docker/pty-types.d.ts +4 -0
  70. package/dist/docker/pty-types.js.map +1 -1
  71. package/dist/escalation/escalation-watcher.d.ts +3 -1
  72. package/dist/escalation/escalation-watcher.js +6 -2
  73. package/dist/escalation/escalation-watcher.js.map +1 -1
  74. package/dist/escalation/listener-command.js +24 -10
  75. package/dist/escalation/listener-command.js.map +1 -1
  76. package/dist/escalation/listener-lock.d.ts +5 -0
  77. package/dist/escalation/listener-lock.js +14 -0
  78. package/dist/escalation/listener-lock.js.map +1 -1
  79. package/dist/index.js +6 -1
  80. package/dist/index.js.map +1 -1
  81. package/dist/memory/auto-save.d.ts +25 -0
  82. package/dist/memory/auto-save.js +89 -0
  83. package/dist/memory/auto-save.js.map +1 -0
  84. package/dist/mux/mux-app.d.ts +4 -0
  85. package/dist/mux/mux-app.js +168 -18
  86. package/dist/mux/mux-app.js.map +1 -1
  87. package/dist/mux/mux-command.d.ts +2 -2
  88. package/dist/mux/mux-command.js +14 -22
  89. package/dist/mux/mux-command.js.map +1 -1
  90. package/dist/mux/mux-escalation-manager.d.ts +9 -3
  91. package/dist/mux/mux-escalation-manager.js +69 -19
  92. package/dist/mux/mux-escalation-manager.js.map +1 -1
  93. package/dist/mux/mux-input-handler.d.ts +31 -1
  94. package/dist/mux/mux-input-handler.js +106 -25
  95. package/dist/mux/mux-input-handler.js.map +1 -1
  96. package/dist/mux/mux-renderer.d.ts +17 -1
  97. package/dist/mux/mux-renderer.js +288 -7
  98. package/dist/mux/mux-renderer.js.map +1 -1
  99. package/dist/mux/pty-bridge.d.ts +4 -0
  100. package/dist/mux/pty-bridge.js +13 -1
  101. package/dist/mux/pty-bridge.js.map +1 -1
  102. package/dist/mux/types.d.ts +24 -1
  103. package/dist/mux/types.js +10 -1
  104. package/dist/mux/types.js.map +1 -1
  105. package/dist/persona/persona-command.js +0 -5
  106. package/dist/persona/persona-command.js.map +1 -1
  107. package/dist/pipeline/annotate.js +1 -7
  108. package/dist/pipeline/annotate.js.map +1 -1
  109. package/dist/pipeline/compile.d.ts +5 -2
  110. package/dist/pipeline/compile.js +23 -11
  111. package/dist/pipeline/compile.js.map +1 -1
  112. package/dist/pipeline/constitution-compiler.d.ts +302 -3
  113. package/dist/pipeline/constitution-compiler.js +285 -23
  114. package/dist/pipeline/constitution-compiler.js.map +1 -1
  115. package/dist/pipeline/generate-with-repair.d.ts +2 -2
  116. package/dist/pipeline/generate-with-repair.js +2 -2
  117. package/dist/pipeline/handwritten-scenarios.d.ts +20 -7
  118. package/dist/pipeline/handwritten-scenarios.js +20 -41
  119. package/dist/pipeline/handwritten-scenarios.js.map +1 -1
  120. package/dist/pipeline/list-resolver.d.ts +18 -20
  121. package/dist/pipeline/list-resolver.js +28 -36
  122. package/dist/pipeline/list-resolver.js.map +1 -1
  123. package/dist/pipeline/pipeline-runner.d.ts +102 -13
  124. package/dist/pipeline/pipeline-runner.js +497 -237
  125. package/dist/pipeline/pipeline-runner.js.map +1 -1
  126. package/dist/pipeline/pipeline-shared.d.ts +7 -9
  127. package/dist/pipeline/pipeline-shared.js +8 -18
  128. package/dist/pipeline/pipeline-shared.js.map +1 -1
  129. package/dist/pipeline/policy-verifier.d.ts +32 -5
  130. package/dist/pipeline/policy-verifier.js +137 -8
  131. package/dist/pipeline/policy-verifier.js.map +1 -1
  132. package/dist/pipeline/proxy-mcp-connections.d.ts +25 -0
  133. package/dist/pipeline/proxy-mcp-connections.js +121 -0
  134. package/dist/pipeline/proxy-mcp-connections.js.map +1 -0
  135. package/dist/pipeline/refresh-lists.js +21 -13
  136. package/dist/pipeline/refresh-lists.js.map +1 -1
  137. package/dist/pipeline/scenario-generator.d.ts +29 -49
  138. package/dist/pipeline/scenario-generator.js +180 -143
  139. package/dist/pipeline/scenario-generator.js.map +1 -1
  140. package/dist/pipeline/scenario-schema-validator.d.ts +51 -0
  141. package/dist/pipeline/scenario-schema-validator.js +132 -0
  142. package/dist/pipeline/scenario-schema-validator.js.map +1 -0
  143. package/dist/pipeline/tool-annotator.d.ts +9 -8
  144. package/dist/pipeline/tool-annotator.js +48 -95
  145. package/dist/pipeline/tool-annotator.js.map +1 -1
  146. package/dist/pipeline/types.d.ts +31 -24
  147. package/dist/sandbox/index.js +20 -0
  148. package/dist/sandbox/index.js.map +1 -1
  149. package/dist/servers/fetch-server.js +10 -5
  150. package/dist/servers/fetch-server.js.map +1 -1
  151. package/dist/session/agent-session.d.ts +6 -19
  152. package/dist/session/agent-session.js +18 -69
  153. package/dist/session/agent-session.js.map +1 -1
  154. package/dist/session/base-transport.d.ts +17 -1
  155. package/dist/session/base-transport.js +25 -1
  156. package/dist/session/base-transport.js.map +1 -1
  157. package/dist/session/cli-transport.d.ts +5 -0
  158. package/dist/session/cli-transport.js +48 -25
  159. package/dist/session/cli-transport.js.map +1 -1
  160. package/dist/session/prompts.js +0 -1
  161. package/dist/session/prompts.js.map +1 -1
  162. package/dist/session/session-manager.d.ts +6 -0
  163. package/dist/session/session-manager.js +12 -0
  164. package/dist/session/session-manager.js.map +1 -1
  165. package/dist/session/types.d.ts +6 -1
  166. package/dist/session/types.js.map +1 -1
  167. package/dist/signal/signal-bot-daemon.js +24 -8
  168. package/dist/signal/signal-bot-daemon.js.map +1 -1
  169. package/dist/signal/signal-transport.d.ts +5 -2
  170. package/dist/signal/signal-transport.js +3 -3
  171. package/dist/signal/signal-transport.js.map +1 -1
  172. package/dist/trusted-process/approval-whitelist.d.ts +117 -0
  173. package/dist/trusted-process/approval-whitelist.js +237 -0
  174. package/dist/trusted-process/approval-whitelist.js.map +1 -0
  175. package/dist/trusted-process/gworkspace-credentials.d.ts +40 -0
  176. package/dist/trusted-process/gworkspace-credentials.js +45 -0
  177. package/dist/trusted-process/gworkspace-credentials.js.map +1 -0
  178. package/dist/trusted-process/index.d.ts +11 -1
  179. package/dist/trusted-process/index.js +63 -27
  180. package/dist/trusted-process/index.js.map +1 -1
  181. package/dist/trusted-process/mcp-proxy-server.d.ts +14 -0
  182. package/dist/trusted-process/mcp-proxy-server.js +325 -64
  183. package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
  184. package/dist/trusted-process/policy-engine.d.ts +8 -2
  185. package/dist/trusted-process/policy-engine.js +18 -22
  186. package/dist/trusted-process/policy-engine.js.map +1 -1
  187. package/dist/trusted-process/policy-types.d.ts +17 -0
  188. package/dist/trusted-process/sandbox-integration.d.ts +23 -0
  189. package/dist/trusted-process/sandbox-integration.js +115 -3
  190. package/dist/trusted-process/sandbox-integration.js.map +1 -1
  191. package/dist/trusted-process/token-file-refresher.d.ts +69 -0
  192. package/dist/trusted-process/token-file-refresher.js +120 -0
  193. package/dist/trusted-process/token-file-refresher.js.map +1 -0
  194. package/dist/types/argument-roles.d.ts +7 -1
  195. package/dist/types/argument-roles.js +50 -0
  196. package/dist/types/argument-roles.js.map +1 -1
  197. package/dist/types/audit.d.ts +11 -0
  198. package/docker/Dockerfile.claude-code +2 -2
  199. package/docker/entrypoint-claude-code.sh +15 -5
  200. package/package.json +3 -2
  201. package/src/config/constitution-user-base.md +15 -0
  202. package/src/config/generated/test-scenarios.json +1 -1
  203. package/src/config/generated/tool-annotations.json +10617 -296
  204. package/src/config/mcp-servers.json +23 -0
  205. package/dist/pipeline/mcp-connections.d.ts +0 -16
  206. package/dist/pipeline/mcp-connections.js +0 -61
  207. package/dist/pipeline/mcp-connections.js.map +0 -1
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CLI entry point for `ironcurtain auth` subcommands.
3
+ *
4
+ * Manages third-party OAuth providers: credential import, authorization,
5
+ * status checking, and token revocation.
6
+ *
7
+ * Subcommands:
8
+ * ironcurtain auth - show status of all providers
9
+ * ironcurtain auth import <provider> <file> - import OAuth client credentials
10
+ * ironcurtain auth <provider> - authorize a provider (opens browser)
11
+ * ironcurtain auth <provider> --scopes x,y - authorize with additional scopes
12
+ * ironcurtain auth status - same as no args
13
+ * ironcurtain auth revoke <provider> - revoke and delete stored token
14
+ */
15
+ export declare function runAuthCommand(args: string[]): Promise<void>;
@@ -0,0 +1,424 @@
1
+ /**
2
+ * CLI entry point for `ironcurtain auth` subcommands.
3
+ *
4
+ * Manages third-party OAuth providers: credential import, authorization,
5
+ * status checking, and token revocation.
6
+ *
7
+ * Subcommands:
8
+ * ironcurtain auth - show status of all providers
9
+ * ironcurtain auth import <provider> <file> - import OAuth client credentials
10
+ * ironcurtain auth <provider> - authorize a provider (opens browser)
11
+ * ironcurtain auth <provider> --scopes x,y - authorize with additional scopes
12
+ * ironcurtain auth status - same as no args
13
+ * ironcurtain auth revoke <provider> - revoke and delete stored token
14
+ */
15
+ import { copyFileSync, existsSync, chmodSync, mkdirSync } from 'node:fs';
16
+ import { resolve } from 'node:path';
17
+ import { parseArgs } from 'node:util';
18
+ import * as p from '@clack/prompts';
19
+ import { printHelp } from '../cli-help.js';
20
+ import { getOAuthDir, getOAuthTokenPath } from '../config/paths.js';
21
+ import { loadClientCredentials } from './oauth-provider.js';
22
+ import { getAllOAuthProviders, printAvailableProviders, resolveProviderOrExit } from './oauth-registry.js';
23
+ import { runOAuthFlow, fetchWithTimeout } from './oauth-flow.js';
24
+ import { deleteOAuthToken, loadOAuthToken, saveOAuthToken } from './oauth-token-store.js';
25
+ // ---------------------------------------------------------------------------
26
+ // Help specs
27
+ // ---------------------------------------------------------------------------
28
+ const authSpec = {
29
+ name: 'ironcurtain auth',
30
+ description: 'Manage third-party OAuth providers for MCP servers',
31
+ usage: [
32
+ 'ironcurtain auth # Show provider status',
33
+ 'ironcurtain auth import <provider> <file> # Import client credentials',
34
+ 'ironcurtain auth <provider> # Authorize (opens browser)',
35
+ 'ironcurtain auth <provider> --scopes <scopes> # Authorize with extra scopes',
36
+ 'ironcurtain auth revoke <provider> # Revoke stored token',
37
+ 'ironcurtain auth status # Show provider status',
38
+ ],
39
+ subcommands: [
40
+ { name: 'import <provider> <file>', description: 'Import OAuth client credentials from provider' },
41
+ { name: '<provider>', description: 'Authorize a provider (opens browser for OAuth flow)' },
42
+ { name: 'revoke <provider>', description: 'Revoke and delete stored OAuth token' },
43
+ { name: 'status', description: 'Show authorization status for all providers' },
44
+ ],
45
+ options: [
46
+ { flag: 'scopes', description: 'Comma-separated scopes for incremental consent', placeholder: '<scopes>' },
47
+ { flag: 'help', short: 'h', description: 'Show this help message' },
48
+ ],
49
+ examples: [
50
+ 'ironcurtain auth import google ~/Downloads/credentials.json',
51
+ 'ironcurtain auth google',
52
+ 'ironcurtain auth google --scopes gmail.send,calendar.events',
53
+ 'ironcurtain auth revoke google',
54
+ 'ironcurtain auth status',
55
+ ],
56
+ };
57
+ // ---------------------------------------------------------------------------
58
+ // Google Cloud setup guide (shown when credentials are missing)
59
+ // ---------------------------------------------------------------------------
60
+ const GOOGLE_SETUP_GUIDE = `
61
+ Google Cloud Project Setup
62
+ ==========================
63
+
64
+ IronCurtain requires you to create your own Google Cloud OAuth credentials.
65
+ This is a one-time setup.
66
+
67
+ Step 1: Create a Google Cloud Project
68
+ Go to https://console.cloud.google.com/projectcreate
69
+ Enter a project name (e.g., "IronCurtain") and click Create.
70
+
71
+ Step 2: Enable Google Workspace APIs
72
+ Navigate to APIs & Services > Library and enable:
73
+ - Gmail API
74
+ - Google Calendar API
75
+ - Google Drive API
76
+
77
+ Step 3: Configure the OAuth Consent Screen
78
+ Navigate to APIs & Services > OAuth consent screen
79
+ Set User type to "External" (or "Internal" for Google Workspace orgs)
80
+ Fill in App name, support email, and developer contact email.
81
+ Add scopes based on what you need:
82
+ Read-only (default): gmail.readonly, calendar.readonly, drive.readonly
83
+ Write access: gmail.send, calendar.events, drive.file
84
+ You choose which scopes to enable — write scopes are optional.
85
+ Under Test users, add your Google account email.
86
+
87
+ Note: In "Testing" mode, refresh tokens expire after 7 days.
88
+ You will need to re-authorize weekly.
89
+
90
+ To add write scopes after initial authorization:
91
+ ironcurtain auth google --scopes gmail.send,calendar.events
92
+
93
+ Step 4: Create OAuth Client Credentials
94
+ Navigate to APIs & Services > Credentials
95
+ Click "Create Credentials" > "OAuth client ID"
96
+ Select Application type: "Desktop app"
97
+ Enter a name (e.g., "IronCurtain CLI")
98
+ Click Create, then "Download JSON"
99
+
100
+ Step 5: Import into IronCurtain
101
+ ironcurtain auth import google /path/to/downloaded-credentials.json
102
+
103
+ For more details, see: docs/designs/third-party-oauth.md
104
+ `;
105
+ /** Provider-specific setup guides, keyed by provider ID. */
106
+ const SETUP_GUIDES = {
107
+ google: GOOGLE_SETUP_GUIDE,
108
+ };
109
+ function showSetupGuide(providerId) {
110
+ const guide = SETUP_GUIDES[providerId];
111
+ if (guide) {
112
+ process.stdout.write(guide);
113
+ }
114
+ }
115
+ function truncate(value, maxLen) {
116
+ return value.length > maxLen ? value.slice(0, maxLen) + '...' : value;
117
+ }
118
+ // ---------------------------------------------------------------------------
119
+ // Import credentials
120
+ // ---------------------------------------------------------------------------
121
+ /**
122
+ * Handles `ironcurtain auth import <provider> <credentials-file>`.
123
+ * Shows provider-specific setup guidance when credentials file is not provided.
124
+ */
125
+ function importCredentials(args) {
126
+ const providerId = args[0];
127
+ const credentialsPath = args[1];
128
+ if (!providerId) {
129
+ process.stdout.write('Usage: ironcurtain auth import <provider> <credentials-file>\n\n');
130
+ printAvailableProviders();
131
+ process.exit(1);
132
+ }
133
+ const provider = resolveProviderOrExit(providerId);
134
+ if (!credentialsPath) {
135
+ process.stdout.write(`Usage: ironcurtain auth import ${providerId} <credentials-file>\n`);
136
+ process.stdout.write('\nProvide the path to the credentials JSON file downloaded from your provider.\n');
137
+ showSetupGuide(provider.id);
138
+ process.exit(1);
139
+ return;
140
+ }
141
+ const resolvedPath = resolve(credentialsPath);
142
+ // Ensure the oauth directory exists and copy the file
143
+ const oauthDir = getOAuthDir();
144
+ mkdirSync(oauthDir, { recursive: true });
145
+ const destPath = resolve(oauthDir, provider.credentialsFilename);
146
+ try {
147
+ copyFileSync(resolvedPath, destPath);
148
+ chmodSync(destPath, 0o600);
149
+ }
150
+ catch (err) {
151
+ const message = err instanceof Error ? err.message : String(err);
152
+ process.stdout.write(`Failed to import credentials: ${message}\n`);
153
+ process.exit(1);
154
+ }
155
+ // Validate by loading the copied credentials
156
+ const credentials = loadClientCredentials(provider);
157
+ if (!credentials) {
158
+ process.stdout.write(`Invalid credentials file: could not extract client_id and client_secret.\n`);
159
+ process.exit(1);
160
+ }
161
+ process.stdout.write(`\n ${provider.displayName} -- Import OAuth Credentials\n\n`);
162
+ process.stdout.write(` Found client_id: ${truncate(credentials.clientId, 20)}\n`);
163
+ process.stdout.write(` Credentials saved to ${destPath}\n\n`);
164
+ process.stdout.write(` Next step: run 'ironcurtain auth ${provider.id}' to authorize.\n\n`);
165
+ }
166
+ // ---------------------------------------------------------------------------
167
+ // Status display
168
+ // ---------------------------------------------------------------------------
169
+ function showStatus() {
170
+ const providers = getAllOAuthProviders();
171
+ if (providers.length === 0) {
172
+ process.stdout.write('No OAuth providers registered.\n');
173
+ return;
174
+ }
175
+ process.stdout.write('\nOAuth Provider Status:\n\n');
176
+ for (const provider of providers) {
177
+ let credStatus;
178
+ try {
179
+ credStatus = loadClientCredentials(provider) !== null ? 'configured' : 'not configured';
180
+ }
181
+ catch {
182
+ credStatus = 'invalid';
183
+ }
184
+ const tokenPath = getOAuthTokenPath(provider.id);
185
+ const hasToken = existsSync(tokenPath);
186
+ const tokenStatus = hasToken ? 'authorized' : 'not authorized';
187
+ process.stdout.write(` ${provider.displayName} (${provider.id})\n`);
188
+ process.stdout.write(` Credentials: ${credStatus}\n`);
189
+ process.stdout.write(` Token: ${tokenStatus}\n`);
190
+ process.stdout.write('\n');
191
+ }
192
+ }
193
+ // ---------------------------------------------------------------------------
194
+ // Revoke
195
+ // ---------------------------------------------------------------------------
196
+ /**
197
+ * Attempts to revoke the token server-side via the provider's revocation
198
+ * endpoint (if configured), then deletes the local token file.
199
+ */
200
+ async function revokeToken(providerId) {
201
+ const provider = resolveProviderOrExit(providerId);
202
+ const token = loadOAuthToken(provider.id);
203
+ if (!token) {
204
+ process.stdout.write(`No stored token found for ${provider.displayName}.\n`);
205
+ return;
206
+ }
207
+ // Attempt server-side revocation if the provider has a revocation endpoint
208
+ await revokeTokenRemotely(provider, token);
209
+ deleteOAuthToken(provider.id);
210
+ process.stdout.write(`Token revoked for ${provider.displayName}.\n`);
211
+ process.stdout.write(`Deleted: ${getOAuthTokenPath(provider.id)}\n`);
212
+ }
213
+ /**
214
+ * Calls the provider's token revocation endpoint to invalidate the token
215
+ * server-side. Best-effort: logs a warning on failure but does not throw.
216
+ */
217
+ async function revokeTokenRemotely(provider, token) {
218
+ if (!provider.revocationUrl) {
219
+ return;
220
+ }
221
+ // Prefer revoking the refresh token (invalidates both access and refresh)
222
+ const tokenToRevoke = token.refreshToken || token.accessToken;
223
+ const REVOCATION_TIMEOUT_MS = 10_000;
224
+ try {
225
+ const response = await fetchWithTimeout(provider.revocationUrl, {
226
+ method: 'POST',
227
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
228
+ body: new URLSearchParams({ token: tokenToRevoke }).toString(),
229
+ }, REVOCATION_TIMEOUT_MS);
230
+ if (!response.ok) {
231
+ const text = await response.text();
232
+ process.stdout.write(`Warning: Server-side revocation returned ${response.status}: ${text}\n`);
233
+ }
234
+ }
235
+ catch (err) {
236
+ if (err instanceof Error && err.name === 'TimeoutError') {
237
+ process.stdout.write(`Warning: Revocation request timed out after ${REVOCATION_TIMEOUT_MS}ms\n`);
238
+ }
239
+ else {
240
+ const message = err instanceof Error ? err.message : String(err);
241
+ process.stdout.write(`Warning: Could not reach revocation endpoint: ${message}\n`);
242
+ }
243
+ }
244
+ }
245
+ // ---------------------------------------------------------------------------
246
+ // Authorize
247
+ // ---------------------------------------------------------------------------
248
+ /**
249
+ * Parses optional --scopes flag from remaining args after the provider name.
250
+ * Returns the scopes array, or undefined if not specified.
251
+ */
252
+ function parseScopesArg(args) {
253
+ // args is everything after the provider name
254
+ if (args.length === 0) {
255
+ return undefined;
256
+ }
257
+ const scopesFlagPresent = args.includes('--scopes');
258
+ try {
259
+ const { values } = parseArgs({
260
+ args,
261
+ options: {
262
+ scopes: { type: 'string' },
263
+ },
264
+ strict: false,
265
+ });
266
+ if (typeof values.scopes === 'string' && values.scopes.length > 0) {
267
+ return values.scopes
268
+ .split(',')
269
+ .map((s) => s.trim())
270
+ .filter((s) => s.length > 0);
271
+ }
272
+ }
273
+ catch (err) {
274
+ if (scopesFlagPresent) {
275
+ const message = err instanceof Error ? err.message : String(err);
276
+ throw new Error(`Failed to parse --scopes: ${message}`, { cause: err });
277
+ }
278
+ // --scopes not present: ignore unrelated parse errors
279
+ }
280
+ return undefined;
281
+ }
282
+ /**
283
+ * Checks whether any of the selected scopes are non-default for this provider.
284
+ * Used to decide whether to show a consent-screen warning.
285
+ */
286
+ function hasNonDefaultScopes(provider, scopes) {
287
+ const defaults = new Set(provider.defaultScopes);
288
+ return scopes.some((s) => !defaults.has(s));
289
+ }
290
+ /**
291
+ * Shows a warning note about non-default scopes, with optional
292
+ * provider-specific guidance, then prompts for confirmation.
293
+ * Returns false if the user cancels.
294
+ */
295
+ async function confirmNonDefaultScopes(provider, scopes) {
296
+ if (!hasNonDefaultScopes(provider, scopes)) {
297
+ return true;
298
+ }
299
+ const defaults = new Set(provider.defaultScopes);
300
+ const nonDefault = scopes.filter((s) => !defaults.has(s));
301
+ const scopeList = nonDefault.map((s) => ` ${s}`).join('\n');
302
+ const guidance = provider.nonDefaultScopeWarning ??
303
+ 'Ensure these scopes are configured with your OAuth provider\nbefore proceeding.';
304
+ p.note(`The following non-default scopes were selected:\n\n${scopeList}\n\n${guidance}`, 'Non-default scopes selected');
305
+ const confirmed = await p.confirm({
306
+ message: 'Continue with authorization?',
307
+ initialValue: true,
308
+ });
309
+ if (p.isCancel(confirmed) || !confirmed) {
310
+ return false;
311
+ }
312
+ return true;
313
+ }
314
+ async function authorize(providerId, extraArgs) {
315
+ const provider = resolveProviderOrExit(providerId);
316
+ let credentials;
317
+ try {
318
+ credentials = loadClientCredentials(provider);
319
+ }
320
+ catch (err) {
321
+ const message = err instanceof Error ? err.message : String(err);
322
+ process.stdout.write(`Invalid credentials for ${provider.displayName}: ${message}\n`);
323
+ process.stdout.write(`Re-import with: ironcurtain auth import ${provider.id} <credentials-file>\n`);
324
+ process.exit(1);
325
+ }
326
+ if (!credentials) {
327
+ process.stdout.write(`No credentials configured for ${provider.displayName}.\n` +
328
+ `Run 'ironcurtain auth import ${provider.id} <credentials-file>' first.\n`);
329
+ showSetupGuide(provider.id);
330
+ process.exit(1);
331
+ }
332
+ const requestedScopes = parseScopesArg(extraArgs);
333
+ // Determine effective scopes (merge default + existing + requested for incremental consent)
334
+ let effectiveScopes;
335
+ let needsConfirmation = false;
336
+ if (requestedScopes) {
337
+ // --scopes flag: resolve short names and merge with existing
338
+ const resolved = provider.resolveShortScopes ? provider.resolveShortScopes(requestedScopes) : requestedScopes;
339
+ const existingToken = loadOAuthToken(provider.id);
340
+ const existingScopes = existingToken?.scopes ?? [];
341
+ // Always include provider defaults as baseline so --scopes only adds, never drops
342
+ const merged = [...new Set([...provider.defaultScopes, ...existingScopes, ...resolved])];
343
+ effectiveScopes = merged;
344
+ process.stdout.write(`\n ${provider.displayName} OAuth -- Incremental Consent\n\n`);
345
+ if (existingScopes.length > 0) {
346
+ process.stdout.write(' Existing scopes:\n');
347
+ for (const scope of existingScopes) {
348
+ process.stdout.write(` - ${scope}\n`);
349
+ }
350
+ process.stdout.write('\n Requesting additional scopes:\n');
351
+ for (const scope of resolved) {
352
+ if (!existingScopes.includes(scope)) {
353
+ process.stdout.write(` + ${scope}\n`);
354
+ }
355
+ }
356
+ process.stdout.write('\n');
357
+ }
358
+ }
359
+ else if (process.stdin.isTTY && provider.scopePicker) {
360
+ // Interactive TTY: show the scope picker
361
+ const existingToken = loadOAuthToken(provider.id);
362
+ const existingScopes = existingToken?.scopes ?? [];
363
+ const selected = await provider.scopePicker(existingScopes);
364
+ if (p.isCancel(selected)) {
365
+ p.cancel('Authorization cancelled.');
366
+ return;
367
+ }
368
+ effectiveScopes = selected;
369
+ needsConfirmation = true;
370
+ }
371
+ else {
372
+ // Non-interactive: use defaults
373
+ process.stdout.write(`\n ${provider.displayName} OAuth\n\n`);
374
+ process.stdout.write(` Using credentials: ${truncate(credentials.clientId, 30)}\n`);
375
+ process.stdout.write(` Requesting scopes: ${provider.defaultScopes.join(', ')}\n\n`);
376
+ }
377
+ // Warn about non-default scopes and confirm (for interactive picker only)
378
+ if (effectiveScopes && needsConfirmation) {
379
+ const confirmed = await confirmNonDefaultScopes(provider, effectiveScopes);
380
+ if (!confirmed) {
381
+ p.cancel('Authorization cancelled.');
382
+ return;
383
+ }
384
+ }
385
+ process.stdout.write(' Opening browser for authorization...\n');
386
+ const result = await runOAuthFlow(provider, credentials, effectiveScopes);
387
+ saveOAuthToken(provider.id, result.token);
388
+ const tokenPath = getOAuthTokenPath(provider.id);
389
+ process.stdout.write(`\n Authorization successful!\n`);
390
+ process.stdout.write(` Token stored at ${tokenPath}\n`);
391
+ process.stdout.write(` Granted scopes: ${result.grantedScopes.join(', ')}\n\n`);
392
+ }
393
+ // ---------------------------------------------------------------------------
394
+ // Entry point
395
+ // ---------------------------------------------------------------------------
396
+ export async function runAuthCommand(args) {
397
+ const subcommand = args[0];
398
+ // Show help when --help/-h is the first arg or no subcommand is given.
399
+ // Don't intercept --help after a subcommand — let subcommands handle their own help.
400
+ if (subcommand === '--help' || subcommand === '-h') {
401
+ printHelp(authSpec);
402
+ return;
403
+ }
404
+ if (!subcommand || subcommand === 'status') {
405
+ showStatus();
406
+ return;
407
+ }
408
+ if (subcommand === 'import') {
409
+ importCredentials(args.slice(1));
410
+ return;
411
+ }
412
+ if (subcommand === 'revoke') {
413
+ const providerId = args[1];
414
+ if (!providerId) {
415
+ process.stdout.write('Usage: ironcurtain auth revoke <provider>\n');
416
+ process.exit(1);
417
+ }
418
+ await revokeToken(providerId);
419
+ return;
420
+ }
421
+ // Remaining args after the provider name go to authorize for --scopes parsing
422
+ await authorize(subcommand, args.slice(1));
423
+ }
424
+ //# sourceMappingURL=auth-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-command.js","sourceRoot":"","sources":["../../src/auth/auth-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * OAuth 2.0 authorization code flow with PKCE.
3
+ *
4
+ * Runs the complete browser-based flow: generates PKCE challenge,
5
+ * starts an ephemeral callback server, opens the browser, waits for
6
+ * the authorization code, and exchanges it for tokens.
7
+ */
8
+ import type { OAuthProviderConfig, OAuthClientCredentials, StoredOAuthToken } from './oauth-provider.js';
9
+ export interface OAuthFlowResult {
10
+ readonly token: StoredOAuthToken;
11
+ /** The scopes actually granted by the provider (may differ from requested). */
12
+ readonly grantedScopes: readonly string[];
13
+ }
14
+ export declare class OAuthFlowError extends Error {
15
+ constructor(message: string, options?: ErrorOptions);
16
+ }
17
+ export interface OAuthFlowOptions {
18
+ /** Override how the authorization URL is opened (default: system browser). */
19
+ readonly openUrl?: (url: string) => void;
20
+ }
21
+ /** Generates a cryptographically random code verifier (43-128 chars, base64url). */
22
+ export declare function generateCodeVerifier(): string;
23
+ /** Computes the S256 code challenge from a code verifier. */
24
+ export declare function computeCodeChallenge(verifier: string): string;
25
+ /**
26
+ * Runs the OAuth 2.0 authorization code flow with PKCE.
27
+ *
28
+ * 1. Generates PKCE code verifier and challenge
29
+ * 2. Starts an ephemeral HTTP server on 127.0.0.1:0 (OS-assigned port)
30
+ * 3. Opens the authorization URL in the user's default browser
31
+ * 4. Waits for the callback with the authorization code
32
+ * 5. Exchanges the code for tokens using client_id + client_secret
33
+ * 6. Stops the callback server
34
+ */
35
+ export declare function runOAuthFlow(provider: OAuthProviderConfig, clientCredentials: OAuthClientCredentials, scopes?: readonly string[], timeoutMs?: number, options?: OAuthFlowOptions): Promise<OAuthFlowResult>;
36
+ /**
37
+ * Wraps fetch() with an AbortSignal-based timeout.
38
+ * Callers are responsible for catching the AbortError and rethrowing as
39
+ * the appropriate domain error (OAuthFlowError, OAuthTokenExpiredError, etc.).
40
+ */
41
+ export declare function fetchWithTimeout(url: string, init: RequestInit, timeoutMs: number): Promise<Response>;
42
+ /**
43
+ * Safely parses a Response body as JSON.
44
+ * Returns the parsed value, or throws with a descriptive message on failure.
45
+ */
46
+ export declare function safeResponseJson(response: Response): Promise<unknown>;