inspector/clients/web/src/theme
Repository files (latest commit first)
Filename Latest commit message Latest commit date
cliffhall de7795ca54 fix(auth): address Copilot review round 2 on the secret-store PR
Seven findings, all taken.

- **The descriptor went stale after the upgrading write.** Round 1 made it
  read the file instead of the policy, but it was still computed once and
  cached beside the selection — so the first `set` under a newly-set
  passphrase encrypted the file while `/api/config` kept serving "still
  unencrypted" for the rest of the session, describing bytes this very
  process had just changed. The *selection* stays cached (the banner, the
  payload, and the store doing the writing must agree on which store it
  is); the file descriptor is re-derived per call, which costs one read of
  a small file per config fetch.

- **The mount check asked the wrong question.** Comparing a directory's
  `st_dev` against its parent's detects a mount *at* that path, but a
  volume mounted at `/home/node` leaves `/home/node/.mcp-inspector` an
  ordinary subdirectory sharing its parent's device — so a durable
  container setup was judged unmounted and demoted to session-only
  `memory`. It now reads `/proc/self/mountinfo` and asks whether the
  directory is *under* any mount other than `/`, which also catches the
  same-device bind mount no `st_dev` test can see. Where mountinfo is
  unreadable (macOS, Windows, a `/proc`-less container) it falls back to
  the device comparison, now against `/` rather than the parent.

- **A decrypted payload was cast, not checked.** GCM proves the bytes are
  authentic, not that they parse to the right shape. An array passes
  `typeof === "object"`, takes the named assignment, and then
  `JSON.stringify` drops every named property of an array — so `set` would
  resolve having written a file without the secret it was handed. Silent
  loss on the one operation whose entire contract is that it does not lose
  things. Both branches now validate a non-array object of string values,
  and a shape refusal is deliberately not rethrown as a key mismatch,
  which would send the user to fix a working passphrase.

- **The read-modify-write cycle was only serialized in-process.** A
  durable file is shared state and a second Inspector on the same box (a
  CLI run beside a web session) could read the same map and overwrite the
  first one's save, both reporting success. Mutations now take a
  `mkdir`-based lock. A lock left by a killed process is stolen after 10s
  — one `docker kill` must not brick secret writes permanently, which
  would be a worse failure than the race. If the lock cannot be created at
  all, the write proceeds unlocked rather than denying a real user a real
  secret to prevent a race with a process that may not exist. Reads do not
  lock: `writeStoreFile` is atomic, so a reader sees the old file or the
  new one, never a torn one.

- **The permission repair was fire-and-forget while the docs promised
  0600.** A file owned by another user, or on a read-only mount, stayed
  exposed while the footer described it as protected. It now verifies the
  resulting mode and warns, naming the actual mode, when it could not be
  tightened.

- **`Group`'s theme carried a domain-named `secretStorageFooter`
  variant**, which AGENTS.md reserves for app-wide primitive styling.
  Renamed to the structural `stickyModalFooter`; the secret-storage
  meaning stays in the element that owns it.

- The PR description still claimed the salt made a short passphrase safe,
  contradicting the corrected comment and README. Updated.

Tests: both mount layouts that motivated the change (mount-at and
mount-above) plus the sibling-prefix, space-escaped, first-run, and
no-mountinfo cases; the array and non-string refusals on both the
plaintext and the authentic-ciphertext paths (the latter through a
hand-built fixture, since the store's own writer cannot produce that
state); lock exclusion, stale-lock stealing, the un-lockable fallback, and
two independent store instances racing; the permission report in all three
states; and the descriptor no longer going stale within one process. Full
`npm run ci` green — 5,688 tests under the coverage gate.

Signed-off-by: cliffhall <cliff@futurescale.com>
2026-08-22 12:51:14 -04:00
..
assets refine UI layout, theming, and component consistency across screens 2026-03-23 16:56:53 -04:00
Accordion.ts refactor(web): rename "History" tab/feature to "Protocol" (#1623) 2026-07-09 19:04:54 -04:00
ActionIcon.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
Alert.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
AppShell.ts fix(web): hide resource subscription UI when server lacks subscribe capability (#1479) 2026-06-14 12:54:19 -04:00
Autocomplete.ts fix(web): section-header hover outline + clear buttons out of tab order (#1487) (#1488) 2026-06-14 22:27:46 -04:00
Badge.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
Button.ts formatting 2026-03-17 16:43:27 -04:00
Card.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
Code.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
Flex.ts Add new components, typography, badge contrast, and screen layout refactors 2026-03-28 20:38:04 -04:00
Group.ts fix(auth): address Copilot review round 2 on the secret-store PR 2026-08-22 12:51:14 -04:00
index.ts web: pin Server/Client Settings modal header while body scrolls (#1753) 2026-07-23 19:57:03 -04:00
Input.ts Phase 1: Style refinements and component tweaks from Storybook review 2026-04-17 19:26:21 -04:00
Modal.ts web: pin Server/Client Settings modal header while body scrolls (#1753) 2026-07-23 19:57:03 -04:00
Paper.test.tsx chore: close a batch of quality-gate & tidy gaps (#1785 #1787 #1789 #1790 #1767) (#1792) 2026-07-26 10:43:11 -04:00
Paper.ts Add new components, typography, badge contrast, and screen layout refactors 2026-03-28 20:38:04 -04:00
ScrollArea.ts web: Accessibility — accessible palette + WCAG AA contrast, labels, names, roles (#1679) 2026-07-13 18:20:55 -04:00
Select.ts formatting 2026-03-17 16:43:27 -04:00
Switch.ts formatting 2026-03-17 16:43:27 -04:00
Text.ts web: server-screen, footer, monitoring-sidebar, and responsive-header polish (#1683) 2026-07-14 08:55:39 -04:00
TextInput.ts formatting 2026-03-17 16:43:27 -04:00
theme.ts web: pin Server/Client Settings modal header while body scrolls (#1753) 2026-07-23 19:57:03 -04:00
Title.ts feat(connection-info): wire Connection Info modal to the connection handshake (#1377) 2026-05-30 16:42:37 -04:00
UnstyledButton.ts fix(web): filter toggle hover as border, not background (#1460) (#1461) 2026-06-13 19:52:27 -04:00