@profoundlogic/coderflow-cli 0.12.112 → 0.12.114

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.
@@ -243,6 +243,43 @@ async function ssoLogin() {
243
243
  }
244
244
  }
245
245
 
246
+ /**
247
+ * Complete a TOTP challenge for a pending CLI login.
248
+ * Prompts for codes (retrying on invalid input) and returns the successful
249
+ * verification response (which contains the API key).
250
+ *
251
+ * `requestFn` and `promptFn` are injectable for testing; they default to the
252
+ * module's real HTTP client and readline prompt.
253
+ * @param {string} mfaToken
254
+ * @param {{ requestFn?: Function, promptFn?: Function, maxAttempts?: number }} [deps]
255
+ * @returns {Promise<object>} response with apiKey
256
+ */
257
+ export async function verifyTotpChallenge(mfaToken, { requestFn = request, promptFn = prompt, maxAttempts = 3 } = {}) {
258
+ console.log('');
259
+ console.log('Multi-factor authentication is required.');
260
+
261
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
262
+ const code = (await promptFn('Authenticator code: ')).trim();
263
+
264
+ try {
265
+ return await requestFn('/auth/mfa/login/verify', {
266
+ method: 'POST',
267
+ body: JSON.stringify({ mfaToken, code })
268
+ });
269
+ } catch (error) {
270
+ // The challenge token expired or was exhausted — cannot retry.
271
+ if (error.statusCode === 401) {
272
+ throw error;
273
+ }
274
+ if (attempt < maxAttempts) {
275
+ console.error(`Invalid code (${maxAttempts - attempt} attempt(s) left). Please try again.`);
276
+ } else {
277
+ throw error;
278
+ }
279
+ }
280
+ }
281
+ }
282
+
246
283
  /**
247
284
  * Username/password login flow
248
285
  */
@@ -270,7 +307,7 @@ async function passwordLogin() {
270
307
 
271
308
  try {
272
309
  // Call the CLI login endpoint (doesn't require auth)
273
- const response = await request('/auth/cli-login', {
310
+ let response = await request('/auth/cli-login', {
274
311
  method: 'POST',
275
312
  body: JSON.stringify({
276
313
  username: username.trim(),
@@ -278,6 +315,20 @@ async function passwordLogin() {
278
315
  })
279
316
  });
280
317
 
318
+ // Required-mode users who have not enrolled cannot complete TOTP from the
319
+ // CLI in this release — direct them to the browser.
320
+ if (response.mfaEnrollmentRequired) {
321
+ console.error('');
322
+ console.error('✗ Multi-factor authentication enrollment required.');
323
+ console.error(response.message || 'Please complete first-time TOTP enrollment in the web browser, then run login again.');
324
+ process.exit(1);
325
+ }
326
+
327
+ // Enrolled users must pass a TOTP challenge before a key is issued.
328
+ if (response.mfaRequired) {
329
+ response = await verifyTotpChallenge(response.mfaToken);
330
+ }
331
+
281
332
  // Save API key to config file or active profile
282
333
  await saveApiKey(response.apiKey);
283
334
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profoundlogic/coderflow-cli",
3
- "version": "0.12.112",
3
+ "version": "0.12.114",
4
4
  "description": "AI Coder CLI - Command-line interface for managing AI coding tasks",
5
5
  "main": "coder.js",
6
6
  "type": "module",