feat(oauth): support recoverable profile rename - #260
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 25 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughNative OAuth profile renames now update configuration, OS-vault credentials, and connection metadata through a recoverable journaled transaction. Startup recovery, locking, audit events, CLI/HTTP errors, documentation, and failure-path tests were added. ChangesNative OAuth profile rename
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant ProfileRename
participant Journal
participant Vault
participant Registry
Client->>ProfileRename: request profile rename
ProfileRename->>Journal: persist intent and source backup
ProfileRename->>Vault: migrate exact credential keys
ProfileRename->>Registry: migrate non-secret binding metadata
ProfileRename->>Journal: finalize and remove recovery artifacts
Possibly related PRs
Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 1 warning)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/cli.md`:
- Line 33: Update the documentation row for miftah profile rename to include the
interrupted-rename recovery contract: document that
OAUTH_PROFILE_RENAME_RECOVERY_REQUIRED is surfaced as a CLI failure with exit
code 1 and operators must retry the same command surface rather than
hand-editing state, matching the existing README guidance.
In `@docs/console-api.md`:
- Line 36: Update the endpoint summary table row for POST
/api/v1/profiles/rename to document atomic native-OAuth credential and metadata
migration, rather than rejecting configured native OAuth bindings or claiming
credentials never move. Also document the OAUTH_PROFILE_RENAME_RECOVERY_REQUIRED
outcome as HTTP 409 oauth_profile_rename_recovery_required, matching
console-server.ts.
In `@src/console/console-server.ts`:
- Around line 422-428: Update the error mapping near the existing
OAUTH_PROFILE_RENAME_RECOVERY_REQUIRED branch to handle error.code
PROFILE_SELECTION_STALE, returning a stable 409 ConsoleHttpError with the
appropriate client-facing error identifier and message instructing clients to
reload configuration before retrying.
In `@src/oauth/connection-lifecycle.ts`:
- Around line 246-265: Update status() to avoid waiting the full refresh lock
budget for read-only status checks: derive the expiry state from the current
record without acquiring the cross-process binding lock, and only acquire the
lock when a credential-state write is required, reloading the record before
persisting to avoid overwriting refresh changes.
In `@src/oauth/connection-registry.ts`:
- Around line 164-178: The profile-only binding equality predicate is duplicated
across the registry and rename transaction. Add one shared predicate beside
sameOAuthConnectionBinding in src/oauth/connection-types.ts, then delete
validProfileBindingMigration in src/oauth/connection-registry.ts (lines 164-178)
and sameBindingExceptProfile in src/oauth/profile-rename-transaction.ts (lines
227-240), importing and using the shared predicate at both call sites.
In `@src/oauth/profile-rename-transaction.ts`:
- Around line 557-558: Handle the return value of
dependencies.registry.migrateProfileBinding in the profile-rename transaction
and call recoveryRequired() when it returns undefined while the binding has
recorded originalMetadata. Preserve normal forward completion when a record is
migrated or no metadata snapshot exists, matching the module’s existing
divergence handling.
- Around line 399-430: Update readSourceBackup to lstat journal.sourceBackupPath
before calling readConfigMigrationSource, and reject recovery when the result is
not a regular file or is a symbolic link. Keep validBackupPath and the existing
sourceHash validation unchanged, and ensure cleanupJournal cannot operate on an
accepted symlink path.
- Around line 707-722: Extend the binding validation in the exported
profile-rename entrypoint around the existing request.bindings checks to match
parseJournal invariants: reject more than 128 bindings, reject duplicate from
credential keys, and require every binding to share one from.profile/to.profile
pair. Keep the existing identity and sameBindingExceptProfile validation, and
throw the established OAUTH_CONNECTION_INVALID error for each invalid set before
writing the journal.
- Around line 496-520: Update cleanupJournal to remove the journal via
store.remove(configPath) before deleting journal.sourceBackupPath, keeping the
verified source bytes available for rollback if journal removal fails. Preserve
the existing error handling and ensure backup deletion occurs only after the
journal is successfully removed, so a crash leaves at most an orphaned backup.
- Around line 783-788: Update createPlatformOAuthProfileRenameDependencies to
accept a shared SecretRedactor and pass it to createPlatformOAuthCredentialStore
instead of allowing the store to create its fallback redactor. Update each
profile-rename entrypoint that calls this dependency factory to supply the same
redactor instance used by the surrounding flow.
In `@tests/oauth-profile-rename-transaction.test.ts`:
- Around line 31-60: Replace the local MemoryCredentialStore and
MemoryMetadataStore definitions with the shared
MemoryProfileRenameCredentialStore and MemoryProfileRenameMetadataStore from the
profile-rename OAuth dependencies helper. Extend the shared credential store
only as needed to support this test’s failOldDelete behavior, then configure
that hook in the test while preserving the existing deletion failure semantics.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 55676347-ff14-4e73-a769-951e0f6a7f70
📒 Files selected for processing (25)
README.mddocs/cli.mddocs/console-api.mdsrc/cli/exit-codes.tssrc/cli/migrate-config.tssrc/console/console-application-service.tssrc/console/console-assets.tssrc/console/console-server.tssrc/oauth/connection-lifecycle.tssrc/oauth/connection-registry.tssrc/oauth/local-state-paths.tssrc/oauth/profile-rename-transaction.tssrc/oauth/remote-oauth-runtime.tssrc/oauth/secure-credential-store.tssrc/setup/profile-rename-onboarding.tssrc/utils/errors.tstests/cli-exit-codes.test.tstests/console-application-service.test.tstests/console-server.test.tstests/helpers/profile-rename-oauth-dependencies.tstests/oauth-profile-rename-transaction.test.tstests/oauth-secure-credential-store.test.tstests/profile-rename-onboarding.test.tstests/readme-product-contract.test.tstests/remote-oauth-runtime.test.ts
b14408c to
9cf1690
Compare
9cf1690 to
e851344
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/oauth/profile-rename-transaction.ts`:
- Around line 525-539: Move the target-key absence validation before
captureJournal and store.create, so any existing target credential is rejected
as a normal collision before the transaction becomes rollback-capable. Keep
prepareTargetCredentials as the in-transaction invariant check, but ensure the
precondition uses the appropriate target-conflict error rather than
recoveryRequired, preventing rollback from deleting credentials this transaction
did not create.
In `@src/setup/profile-rename-onboarding.ts`:
- Around line 252-313: Remove PROFILE_RENAME_OAUTH_CONNECTION from the public
error contract, including its MiftahErrorCode declaration, ERROR_EXIT_CODES
entry, and HTTP error mapping. Verify no remaining references advertise or
depend on this unreachable outcome, without adding a new throw site.
In `@tests/oauth-profile-rename-transaction.test.ts`:
- Around line 359-441: Add a test covering runProfileRename when credentials
already exist at both oldBinding and the target newBinding before execution.
Assert the rename fails through the expected rollback/recovery path and that the
pre-existing target credential remains intact after failure, exercising
prepareTargetCredentials’ to !== undefined branch and preventing
completeRollback from deleting it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f11f3802-0dad-444a-b81e-82cc8bec54f0
📒 Files selected for processing (30)
README.mddocs/cli.mddocs/console-api.mdsrc/cli/exit-codes.tssrc/cli/migrate-config.tssrc/console/console-application-service.tssrc/console/console-assets.tssrc/console/console-server.tssrc/oauth/connection-lifecycle.tssrc/oauth/connection-registry.tssrc/oauth/connection-types.tssrc/oauth/local-state-paths.tssrc/oauth/profile-rename-transaction.tssrc/oauth/remote-oauth-runtime.tssrc/oauth/secure-credential-store.tssrc/setup/profile-rename-onboarding.tssrc/utils/errors.tstests/cli-exit-codes.test.tstests/console-application-service.test.tstests/console-server.test.tstests/helpers/profile-rename-oauth-dependencies.tstests/oauth-connection-lifecycle.test.tstests/oauth-connection-registry.test.tstests/oauth-connection-types.test.tstests/oauth-console-threat-model-docs-contract.test.tstests/oauth-profile-rename-transaction.test.tstests/oauth-secure-credential-store.test.tstests/profile-rename-onboarding.test.tstests/readme-product-contract.test.tstests/remote-oauth-runtime.test.ts
Part of #204.
What changed
Validation
Known local aggregate-test infrastructure
Summary by CodeRabbit