Add Step-up rechallenge implementation#2869
Open
rinatkhaziev wants to merge 17 commits into
Open
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also extracts API_HOST/API_URL/PRODUCTION_API_HOST into a leaf constants module and lazy-requires the rechallenge link inside API() to break a circular-dependency cycle that caused Jest mocks to misfire in the rechallenge test suite.
Implements `vip defensive-mode configure` with full flag validation, interactive prompting for missing required flags, and non-interactive hard-error mode.
…e guards, telemetry order, teardown race) - configure: log current effective config and proposed input before mutating (Fix 1) - enable/disable: add --non-interactive option and guard; error on production mutation attempted non-interactively without --skip-confirmation (Fix 2) - flow: add clientType=cli to rechallenge_required event (Fix 3) - flow: fire rechallenge_verified before rechallenge_exchanged to match spec order (Fix 4) - link: split innerSub into firstSub/retrySub to eliminate teardown race during async gap (Fix 5) - enable/disable/configure: use console.error for error-path chalk.red messages (Fix 6) - token-cache: document single-blob keychain strategy (Fix 7) - tests: assert proposed config logged in configure; add non-interactive-production exit tests for enable/disable; assert rechallenge_verified fires before rechallenge_exchanged Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a new “step-up / rechallenge” elevated-permissions flow that integrates with the existing Apollo GraphQL client (via a custom ApolloLink), adds an elevated-token cache, and wires the flow into logout. It also adds a new vip defensive-mode CLI command group backed by new defensive-mode GraphQL mutations, along with a broad suite of unit tests around these behaviors.
Changes:
- Add rechallenge (step-up) client, flow orchestration, ApolloLink integration, error types, and elevated-token keychain cache.
- Add defensive-mode GraphQL mutation helpers and new CLI commands (
vip defensive-mode enable|disable|configure). - Add unit tests for rechallenge components, defensive-mode API, logout behavior, and defensive-mode command behavior.
Reviewed changes
Copilot reviewed 22 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/token.ts | Switches API host/constants import to avoid pulling full api.ts graph. |
| src/lib/rechallenge/types.ts | Defines rechallenge protocol/types and constants. |
| src/lib/rechallenge/token-cache.ts | Implements keychain-backed elevated-token cache keyed by scope. |
| src/lib/rechallenge/open-browser.ts | Adds wrapper around ESM-only open for browser launching. |
| src/lib/rechallenge/link.ts | Adds ApolloLink that pre-attaches cached elevated token and runs rechallenge on elevated-permission errors. |
| src/lib/rechallenge/index.ts | Exposes rechallenge module exports. |
| src/lib/rechallenge/flow.ts | Implements rechallenge orchestration (session create → poll → exchange → cache). |
| src/lib/rechallenge/errors.ts | Adds typed rechallenge error classes. |
| src/lib/rechallenge/client.ts | Adds HTTP client for rechallenge session/status/exchange endpoints. |
| src/lib/logout.ts | Clears elevated-token cache on logout in addition to primary token purge. |
| src/lib/defensive-mode/api.ts | Adds GraphQL mutations/helpers to update defensive-mode status/config. |
| src/lib/api/http.ts | Switches API_HOST import to new constants module (reduces circular deps). |
| src/lib/api/feature-flags.ts | Lazy-initializes Apollo client to break a circular dependency chain. |
| src/lib/api/constants.ts | Introduces shared API host/URL constants (re-exported by api.ts). |
| src/lib/api.ts | Re-exports constants and injects rechallenge link via lazy require() to avoid Jest mock timing issues. |
| src/bin/vip.js | Registers the new defensive-mode top-level CLI command. |
| src/bin/vip-defensive-mode.js | Adds vip defensive-mode parent command and subcommand wiring. |
| src/bin/vip-defensive-mode-enable.js | Adds vip defensive-mode enable command implementation. |
| src/bin/vip-defensive-mode-disable.js | Adds vip defensive-mode disable command implementation. |
| src/bin/vip-defensive-mode-configure.js | Adds vip defensive-mode configure command implementation with flag validation/prompting. |
| package.json | Adds new vip-defensive-mode* bin entries for distribution. |
| tests/lib/rechallenge/token-cache.test.ts | Unit tests for elevated-token cache behavior and corruption handling. |
| tests/lib/rechallenge/link.test.ts | Unit tests for rechallenge ApolloLink preflight, retry, and error propagation. |
| tests/lib/rechallenge/flow.test.ts | Unit tests for rechallenge flow polling/exchange/caching and interactivity detection. |
| tests/lib/rechallenge/client.test.ts | Unit tests for rechallenge HTTP client request shapes and non-2xx error handling. |
| tests/lib/logout.test.ts | Verifies logout clears both primary token and elevated-token cache + telemetry. |
| tests/lib/defensive-mode/api.test.ts | Verifies defensive-mode mutation input formatting and optional field omission. |
| tests/bin/vip-defensive-mode-enable.js | Tests command registration and enable behavior (including non-interactive production safety). |
| tests/bin/vip-defensive-mode-disable.js | Tests command registration and disable behavior (including non-interactive production safety). |
| tests/bin/vip-defensive-mode-configure.js | Tests configure flag validation, non-interactive behavior, logging, and telemetry. |
Comment on lines
+87
to
+91
| return ( | ||
| result.data as { | ||
| updateDefensiveModeStatus: { success: boolean; message: string }; | ||
| } | ||
| ).updateDefensiveModeStatus; |
Comment on lines
+114
to
+118
| return ( | ||
| result.data as { | ||
| updateDefensiveModeConfig: { success: boolean; message: string }; | ||
| } | ||
| ).updateDefensiveModeConfig; |
Comment on lines
+1
to
+20
| import type { RechallengeStatus } from './types'; | ||
|
|
||
| export class RechallengeError extends Error { | ||
| public readonly scope: string; | ||
| constructor( message: string, scope: string ) { | ||
| super( message ); | ||
| this.name = 'RechallengeError'; | ||
| this.scope = scope; | ||
| } | ||
| } | ||
|
|
||
| export class RechallengeUnsupportedVersionError extends RechallengeError { | ||
| constructor( version: string, scope: string ) { | ||
| super( | ||
| `Server requested rechallenge version "${ version }" but this CLI only supports v2. Update vip-cli.`, | ||
| scope | ||
| ); | ||
| this.name = 'RechallengeUnsupportedVersionError'; | ||
| } | ||
| } |
Comment on lines
+42
to
+49
| const ext = ( err.extensions ?? {} ) as Record< string, unknown >; | ||
| if ( ext.code !== ELEVATED_PERMISSION_ERROR_CODE ) { | ||
| continue; | ||
| } | ||
| const rechallenge = ext.rechallenge as RechallengeExtension | undefined; | ||
| if ( rechallenge && typeof rechallenge.createSessionPath === 'string' ) { | ||
| return { rechallenge }; | ||
| } |
Comment on lines
+1
to
+6
| import { describe, expect, it, jest, beforeEach } from '@jest/globals'; | ||
|
|
||
| import http from '../../../src/lib/api/http'; | ||
| import * as client from '../../../src/lib/rechallenge/client'; | ||
| import { RechallengeHttpError } from '../../../src/lib/rechallenge/errors'; | ||
|
|
…ad validation, dedupe commands) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
This pull request adds a comprehensive suite of unit tests for the new "rechallenge" (elevated permissions) flow and related features. The tests cover the rechallenge client, flow orchestration, Apollo GraphQL link integration, defensive mode API, and logout logic, ensuring that the elevated permissions workflow is robust, correctly integrated, and well-covered by automated tests.
Rechallenge/Elevated Permissions Flow Testing:
__tests__/lib/rechallenge/client.test.ts).__tests__/lib/rechallenge/flow.test.ts).__tests__/lib/rechallenge/link.test.ts).Defensive Mode API Testing:
updateDefensiveModeStatusandupdateDefensiveModeConfigAPI calls, checking input formatting and omission of optional fields (__tests__/lib/defensive-mode/api.test.ts).Logout Flow Testing:
__tests__/lib/logout.test.ts).Changelog Description
Added
Removed
Fixed
Changed
Pull request checklist
New release checklist
Steps to Test
Outline the steps to test and verify the PR here.
Example:
npm run build./dist/bin/vip-cookies.js nom