fix(doctor): merge legacy flat auth repair into existing SQLite store#98245
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 12:33 PM ET / 16:33 UTC. Summary PR surface: Source +21, Tests +47. Total +68 across 2 files. Reproducibility: yes. at source level. Current main writes only the legacy flat store into SQLite during the repair, and the PR body provides copied before/after output from the real repair function using on-disk SQLite state. Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land the focused merge-preserving doctor repair after auth-migration owner review accepts the upgrade-sensitive credential behavior and any needed rebase with related auth migration work. Do we have a high-confidence way to reproduce the issue? Yes at source level. Current main writes only the legacy flat store into SQLite during the repair, and the PR body provides copied before/after output from the real repair function using on-disk SQLite state. Is this the best way to solve the issue? Yes. Reusing the existing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against e62cf76bd50f. Label changesLabel justifications:
Evidence reviewedPR surface: Source +21, Tests +47. Total +68 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
|
This pull request has been automatically marked as stale due to inactivity. |
maybeRepairLegacyFlatAuthProfileStores rewrote the per-agent SQLite auth profile store with a store built solely from the legacy flat auth-profiles.json, and backed up only that flat JSON. Any credential present in SQLite but absent from the flat file (for example an OAuth refresh token from a login after the SQLite migration) was destroyed and was not in the backup, so a routine openclaw doctor caused unrecoverable credential loss. Load the existing SQLite store and merge the legacy flat profiles into it, preserving credentials already present, then verify the imported profiles persisted before removing the flat file, mirroring the SQLite migration path.
0302f28 to
d1392de
Compare
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: fix(doctor): merge legacy flat auth repair into existing SQLite store This is item 1/1 in the current shard. Shard 0/1. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
|
Rank-up moves addressed:
|
|
Merged via squash.
|
…openclaw#98245) maybeRepairLegacyFlatAuthProfileStores rewrote the per-agent SQLite auth profile store with a store built solely from the legacy flat auth-profiles.json, and backed up only that flat JSON. Any credential present in SQLite but absent from the flat file (for example an OAuth refresh token from a login after the SQLite migration) was destroyed and was not in the backup, so a routine openclaw doctor caused unrecoverable credential loss. Load the existing SQLite store and merge the legacy flat profiles into it, preserving credentials already present, then verify the imported profiles persisted before removing the flat file, mirroring the SQLite migration path.
What Problem This Solves
Resolves a problem where running
openclaw doctorcan silently and permanently destroy stored auth credentials. When an install carries an ancient pre-versioned flatauth-profiles.json(a provider to credential map with no{version, profiles}wrapper) alongside a populated SQLite auth profile store, the legacy-flat repair rewrites the entire SQLite store with the flat file's profiles only. Any credential that lives in SQLite but not in the flat file, for example an OAuth refresh token from a login performed after the SQLite migration, is wiped. The backup captures only the flat JSON, so the destroyed SQLite credential is unrecoverable and the affected provider must be re-authenticated. This runs on the defaultopenclaw doctorpath (the auto-fix prompt defaults to yes), so a routine maintenance run is enough to trigger it.Why This Change Was Made
maybeRepairLegacyFlatAuthProfileStoresinsrc/commands/doctor-auth-flat-profiles.tsbuilt its store solely from the flat JSON and then calledsaveAuthProfileStore, which replaces the wholeauth_profile_storeSQLite row instead of merging. This path predates the SQLite auth migration: whole-store overwrite was harmless against a JSON store but became destructive once a populated SQLite store could exist, andbackupAuthProfileStoreonly ever copied the flat JSON.The fix mirrors the sibling SQLite migration (
maybeMigrateAuthProfileJsonStoresToSqlite): load the existing SQLite store, merge the legacy flat profiles into it so existing credentials win, then verify the imported profiles persisted before removing the flat file. It reuses the in-file helpersloadPersistedAuthProfileStore,mergeImportedAuthProfiles, andformatMissingAuthProfileSqliteVerificationrather than adding a second strategy. Behavior is unchanged for the intended case: when SQLite is empty the merge yields exactly the flat profiles. The aws-sdk marker branch in the same function is unaffected; it moves routing metadata into config and never touched the SQLite credential store.This is distinct from open PR #97881, which edits the same file but only in the credential-coercion helpers (
coerceLegacyFlatCredentialand an import) and addresses field loss in the other migration path; it does not touchmaybeRepairLegacyFlatAuthProfileStores. The two changes are in different functions and independent, needing at most a trivial rebase if both land.User Impact
Running
openclaw doctoron an install that still has a legacy flatauth-profiles.jsonno longer deletes SQLite-only credentials. Existing OAuth and API credentials in the SQLite store are preserved, the legacy flat profiles are merged in alongside them, and the flat file is removed only after the imported profiles are confirmed present. If verification fails the flat file is left in place with a warning instead of losing data.Evidence
Drove the real
maybeRepairLegacyFlatAuthProfileStoresagainst a real on-disk per-agent SQLite auth store (populated through the realsaveAuthProfileStore) plus a real legacy flatauth-profiles.json, on pristine main66e676d29band on the patched tree with identical inputs. The auth store, the repair entry point, and the SQLite read-back were all real; nothing was mocked. Steps: seed SQLite with ananthropic:defaultOAuth credential, write a pre-versioned flatauth-profiles.jsonholding onlyopenai, run the repair with auto-fix accepted, then read the raw SQLite store back.On pristine main the
anthropicOAuth profile and its refresh token vanish from SQLite after the repair; with the patch both the preservedanthropicOAuth credential and the migratedopenaikey are present.Additional checks:
node scripts/run-vitest.mjs src/commands/doctor-auth-flat-profiles.test.tspasses 28/28. The new casepreserves existing SQLite auth profiles when migrating a legacy flat storefails on pristine main and passes with the patch.node scripts/run-oxlint.mjsandoxfmt --checkon both changed files are clean.node scripts/run-tsgo.mjs -p tsconfig.core.jsonand-p test/tsconfig/tsconfig.core.test.jsonare clean.