inspector/clients/web/src
Repository files (latest commit first)
Filename Latest commit message Latest commit date
cliffhall af3d940e78 fix(auth): stop a config-only PUT deleting stored secrets (#2084)
Round 24 produced no inline comments again. Of the three suppressed items, one
is a pre-existing data-loss bug that predates #1950 entirely.

**Editing a server's config deletes its stored OAuth client secret — from the
keychain, not only from the stores this PR adds.** Filed as #2084 and fixed
here, since the review surfaced it and these lines were already changing.

`useServers.updateServer` deliberately sends `{ id, config }` with no
`settings`, so a config-only save cannot wipe persisted settings. The route
reads that as `preserve` and re-derives settings from the *on-disk* entry —
which by #1356's design no longer holds the secrets. The submitted secret set
is therefore empty, `expectedSecretFields` always lists the OAuth slot, and
the reconcile deleted a value the user never touched. The rename branch was
given `mergeRenameKeychainSecrets` for exactly this reason; the in-place
branch never got the equivalent.

The first fix was too broad — skip obsolete deletion whenever the intent is
`preserve` — and an existing test caught it immediately: stdio `env` is part
of `config`, so a config-only PUT that drops a key really has retired that
secret. Obsolete detection is per-field now:

- **`env:` fields** are implied by the entry's shape, so the new entry no
  longer expecting one is proof it was retired.
- **The OAuth slot** is implied by nothing, so absence counts as "cleared"
  only when the caller spoke about settings at all.

Both directions are tested, and the pre-existing env-key reconcile test still
passes.

Also:

- `refreshingPersist` moves to `lib/`. The combinator computes nothing, but
  what it exists to do is sequence side effects, which is the `lib` half of
  the repo's split; I judged it the other way on the grounds that the
  function is a pure higher-order one, and the rule is about what a module is
  *for*.
- `SecretStorageInfo.plaintext` is documented as file-only and *omitted*
  elsewhere rather than "always false", which is what the producer does and
  what `usableSecretStorage` enforces — the old wording invited a consumer to
  build the exact shape the web client discards.

Full `npm run ci` green, staged tree verified first.

Signed-off-by: cliffhall <cliff@futurescale.com>
2026-08-22 23:30:17 -04:00
..
components fix(auth): land the round-20 UI wiring that never applied, and nonce the staging name 2026-08-22 22:30:21 -04:00
hooks fix: surface list-fetch failures in paginated mode (#1998) 2026-08-17 20:40:23 -04:00
lib fix(auth): stop a config-only PUT deleting stored secrets (#2084) 2026-08-22 23:30:17 -04:00
test fix(auth): stop a config-only PUT deleting stored secrets (#2084) 2026-08-22 23:30:17 -04:00
theme fix(auth): address Copilot review round 2 on the secret-store PR 2026-08-22 12:51:14 -04:00
types chore: close a batch of quality-gate & tidy gaps (#1785 #1787 #1789 #1790 #1767) (#1792) 2026-07-26 10:43:11 -04:00
utils fix(auth): stop a config-only PUT deleting stored secrets (#2084) 2026-08-22 23:30:17 -04:00
App.css feat(auth): file-backed and in-memory SecretStore for hosts with no keychain 2026-08-22 12:06:31 -04:00
App.test.tsx test: narrow the fake-client cast to a single assertion 2026-08-18 10:52:24 -04:00
App.tsx fix(auth): stop a config-only PUT deleting stored secrets (#2084) 2026-08-22 23:30:17 -04:00
index.ts feat: port CLI, TUI, and launcher from v1.5 into v2 (#1452) 2026-06-14 20:27:49 -04:00
main.tsx fix(web): remove mantine-border-animate, use green highlight border (#1536) 2026-06-27 17:04:25 -04:00