# Linux Electron host-key evidence

Captured 2026-10-22. Baseline runtime: 4eae8ae011. After runtime: f472495255. Final local HEAD: eaeb2149b380fc54b2414e9a747d1ecfd1a6e96c (only adds scripts/ssh-host-key-evidence-fixture.mjs; no runtime changes from requested head). No push, PR edit, or other forge write.

## Result

| Row | Result |
|---|---|
| D1 unknown key / Add Environment SSH | Verified before and after in every requested width/theme. New command and fingerprint guidance; original diagnostic retained. |
| D2 changed key / same dialog | Verified with real OpenSSH and a deliberately mismatched isolated known_hosts entry, not renamed unknown-key output. Full changed-key warning retained. Scrolled supplements expose the long message. |
| S1 saved SSH row / expanded Details / Error | Verified before and after, including opening Details recordings. Saved catalog was seeded, then actual reconnect failed against sshd. |
| P1 provider settings connection.error | UNVERIFIED: actual disconnected-environment route guard shows “Reconnect Host key fixture to change its settings.” ProviderSettingsPanel is not mounted. Four before/after captures document this blocked state, not the proposed error renderer. No invented expansion recording. |

## Environment and capture method

- Real Linux x86_64 Electron 44.9.3, Chromium 152.0.7977.167; kernel 6.1.102; Xvfb 1920×1080×24; no web dev server. Bundled desktop backend used port 3774.
- Native X11 window resized to 1440×1000 and 390×1000. Each snapshot measured matching innerWidth, innerHeight and body layout height. Narrow capture is Electron, not native mobile. DPR 1, Electron zoom 1, 16px interface/root font, font scale 100%. Computed body family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif. fc-match system-ui resolves Liberation Mono Regular on this machine.
- Light/dark used the renderer system color preference; DOM dark class was checked. Reduced-motion preference used for stills. Fonts awaited before captures. Settings and fixture contents retained across baseline/head.
- Isolated T3 home: /home/ubuntu/wt/issue-5869/.desktop-t3. Final baseline/after profiles both use XDG_CONFIG_HOME=/tmp/issue-5869/xdg-config. No read/write connection to live ~/.t3/userdata.
- Direct Electron launch, --no-sandbox --disable-gpu, no pattern-based launcher or killing. Existing shared sshd on port 22269 left running.
- Real /usr/bin/ssh is called by a PATH wrapper with -F /tmp/issue-5869/ssh_config, isolated UserKnownHostsFile and GlobalKnownHostsFile=/dev/null. Unknown fixture empties only the isolated file; changed fixture installs a generated different ED25519 public key. Server host key unchanged. No real known_hosts entry changed or accepted.
- Static evidence supports copy/layout only. The S1 recordings support reaching the diagnostic by opening Details and scrolling. No claim of password-prompt absence, successful retry/trust, timing, or changed interaction behavior.

## Comparison policy and what else changed

Every matched capture has a raw viewport comparison: before, after, absolute RGB difference amplified ×8 with zero threshold, and a binary mask where max absolute RGB-channel delta >16/255. No crop, masking, image registration or hidden dynamic regions. Percentages are changed pixels over all viewport pixels. They are not a pass/fail similarity score.

Copy growth changes centered dialog geometry, wrapping, scroll extent, and the page position reached by scrolling the error into view. Saved-row retry attempts/countdowns and next-retry timestamps differ naturally between captures. Capture times and backend process run IDs differ. The two complete builds differ in the SSH runtime files; test sources stayed at head because they do not enter the desktop bundle. All runtime source files were restored before reporting. Added fixture script is the sole committed difference from requested head.

The after-only scrolled frames exist because added guidance increases content height. They have no corresponding baseline scroll frame and are not reported as diff pairs. P1 unchanged pixels do not establish its requested renderer.

## All comparison sheets

| Capture | Before | After | Sheet: before / after / diff ×8 / >16 mask | Δ>0 | Δ>16 |
|---|---|---|---|---:|---:|
| D1-1440-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/968386f0310adc18/before-D1-1440-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1d8b97ca3e6f8c31/after-D1-1440-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/058ac70c0e5ecf93/D1-1440-light.png) | 25.3075% | 8.2265% |
| D1-1440-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ad497fcc34d96cb6/before-D1-1440-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e973129771bc90e4/after-D1-1440-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fc738c497ac57852/D1-1440-dark.png) | 23.9112% | 5.6850% |
| D1-390-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5545079a27b7fed9/before-D1-390-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/735ec7075c0cc7b5/after-D1-390-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/13405d2759cd77df/D1-390-light.png) | 44.9726% | 15.3513% |
| D1-390-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fc69a834f1f54342/before-D1-390-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/60d2b7cb8a4de872/after-D1-390-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/138145245012076a/D1-390-dark.png) | 47.3954% | 18.3074% |
| D2-1440-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fcda99b6b62a6d0e/before-D2-1440-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/580cdc5c005f9b92/after-D2-1440-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/690e1f8128e85e7a/D2-1440-light.png) | 24.9305% | 10.1865% |
| D2-1440-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a6b79a40666542be/before-D2-1440-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bbddd9824a0a6d84/after-D2-1440-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8b742a848e2d156f/D2-1440-dark.png) | 21.8976% | 7.8106% |
| D2-390-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/eb9aa08263617dae/before-D2-390-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5b2d8cb26a8ec3f5/after-D2-390-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/19274f10ef5cef70/D2-390-light.png) | 5.6913% | 4.7226% |
| D2-390-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/decfe8a690b83065/before-D2-390-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/c8be7caa6564e2b6/after-D2-390-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f28c4be2fbd7bf95/D2-390-dark.png) | 5.7728% | 4.7454% |
| S1-1440-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9dca2ac44458e65a/before-S1-1440-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f88d36e766265237/after-S1-1440-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fcd078198bdeb7c0/S1-1440-light.png) | 2.5343% | 2.2135% |
| S1-1440-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0dad0f32d6e3caa1/before-S1-1440-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fb542e92746bbbdc/after-S1-1440-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a75c33c1ab4e9d0a/S1-1440-dark.png) | 2.5184% | 2.2853% |
| S1-390-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d9123f44d5d04983/before-S1-390-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/5012c5a5c4f80b9b/after-S1-390-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6b6da42badd6b4e8/S1-390-light.png) | 0.1928% | 0.1113% |
| S1-390-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ba739cb967b0b389/before-S1-390-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/d3da6ffb08572ae1/after-S1-390-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a002378291833077/S1-390-dark.png) | 0.1233% | 0.1079% |
| P1-1440-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/dd96cdfe0aeab130/before-P1-1440-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0625bc8600f594a2/after-P1-1440-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/6b5d231906f468bc/P1-1440-light.png) | 0.0059% | 0.0001% |
| P1-1440-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a4fde0c1c7ffe974/before-P1-1440-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ed17d3e521f5c9d7/after-P1-1440-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9eb658619fb9b9f2/P1-1440-dark.png) | 0.0000% | 0.0000% |
| P1-390-light | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a9afa3d48385c284/before-P1-390-light.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bfe7a2da7125a376/after-P1-390-light.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/693177080fc69272/P1-390-light.png) | 0.0000% | 0.0000% |
| P1-390-dark | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4c6cfc9ef1889caf/before-P1-390-dark.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e4757abc93605ebc/after-P1-390-dark.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/9424ec69a91b7b6e/P1-390-dark.png) | 0.0000% | 0.0000% |
| D2-390-dark-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/2d62f1c8c96669d2/before-D2-390-dark-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/345c5c635db03d47/after-D2-390-dark-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b92bd28d33f18474/D2-390-dark-error-1.png) | 19.8526% | 16.8846% |
| D2-390-light-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/4d04dc5546e93e05/before-D2-390-light-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a1cb973c2280ba55/after-D2-390-light-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e04059c7781eca14/D2-390-light-error-1.png) | 20.3459% | 15.8500% |
| S1-1440-dark-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/48844414187d9f11/before-S1-1440-dark-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/158cdba49846b5f1/after-S1-1440-dark-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/31155c19e1d347b6/S1-1440-dark-error-1.png) | 12.7740% | 4.6767% |
| S1-1440-light-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/e00df0f62aa8ce6a/before-S1-1440-light-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a492c2e964390d5e/after-S1-1440-light-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/bb9639077f9c66ee/S1-1440-light-error-1.png) | 12.8994% | 4.6661% |
| S1-390-dark-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/b60864056ab2995f/before-S1-390-dark-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0efdfa435c0e8dac/after-S1-390-dark-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/8286552e551a3735/S1-390-dark-error-1.png) | 29.7749% | 15.6705% |
| S1-390-light-error-1 | [before](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a3b09eb627b57b05/before-S1-390-light-error-1.png) | [after](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/27fc0416cbde9cda/after-S1-390-light-error-1.png) | [sheet](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/fee412cdd680e171/S1-390-light-error-1.png) | 29.9167% | 15.0990% |

## Additional scrolled after captures

- [after-D1-390-dark-error-1.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/f67a1480f6be85d8/after-D1-390-dark-error-1.png) — no baseline frame at this extra scroll extent.
- [after-D1-390-light-error-1.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/48250fffc56185bf/after-D1-390-light-error-1.png) — no baseline frame at this extra scroll extent.
- [after-D2-390-dark-error-2.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/a0df13b2750528f2/after-D2-390-dark-error-2.png) — no baseline frame at this extra scroll extent.
- [after-D2-390-light-error-2.png](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/94ad46d9dffa16ad/after-D2-390-light-error-2.png) — no baseline frame at this extra scroll extent.

## Recordings

S1 steps and observed checkpoints (timestamps are positions in each original recording, inspected at 20 fps; they are not interaction-latency measurements):

1. **00:00.000, both:** Settings > Connections shows the saved “Host key fixture” SSH row with Details collapsed.
2. **00:00.750, both:** Details is expanded and its Error diagnostic is visible below the connection failure details.
3. **00:01.350, both:** The page has scrolled down to expose the diagnostic through its ending, “Host key verification failed.” Before retains the OpenSSH changed-key warning; after adds the terminal SSH command and fingerprint-check guidance before that retained warning.

These are observed checkpoints, not claims about the exact click or scroll onset. The recordings demonstrate opening Details and scrolling to Error, not successful retry, key acceptance, password-prompt absence, or improved interaction timing. Captioned copies add a 100px black band above the intact viewport; no frames were removed or retimed. Original durations remain 3.000s before and 2.150s after. Captions are written narration, not audio.

- [Before, captioned: open saved-row Details and expose Error](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/32ff5d88672851c2/before-S1-open-captioned.mp4)
- [After, captioned: open saved-row Details and expose Error](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/34c83024d40b7463/after-S1-open-captioned.mp4)

Original recording pair: use the same steps and checkpoints above (00:00.000 collapsed; 00:00.750 expanded Error; 00:01.350 scrolled diagnostic ending).

- [Before: open saved-row Details and expose Error](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/311ee3f706ba9d26/before-S1-open.mp4)
- [After: open saved-row Details and expose Error](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/606bf5cbf8d6e98e/after-S1-open.mp4)
- [Machine-readable comparison statistics](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/1710ea054414080b/diff-stats.json)

## Verification and restoration

- Baseline and final `vp run build:desktop`: 5/5 build tasks succeeded each.
- `vp test run packages/ssh/src/command.test.ts packages/ssh/src/tunnel.test.ts`: 2 files, 17 tests passed.
- Fixture script syntax checked; unknown/changed modes exercised; ssh -G confirmed isolated trust paths. Commit hook formatted it. No repo-wide checks.
- Tracked git diff is empty. Only pre-existing untracked .desktop-t3/ remains. No evidence artifacts were committed. Final runtime matches requested head exactly.

## FRICTION / unverified

- P1 is blocked by Settings route guard; see apps/web/src/routes/settings.tsx, environment scope with zero connected environments. This audit discovered the proposed matrix overstates reachability through this route.
- D2 390px dialog retains horizontal clipping on long unbroken warning markers/fingerprint strings. Scrolled screenshots honestly retain it; S1 uses break-all and exposes the full string. No copy was rewritten in the DOM.
- safeStorage required the wrapper’s test keyring password after each new D-Bus session. Unlocking was done outside captures.
- Electron startup overrides --user-data-dir; initial exploratory after captures used the configured app profile. Those were replaced by all final after captures with the same isolated XDG_CONFIG_HOME as baseline.
- macOS/Windows, native mobile, provider-specific behavior, accepting keys and successful retry are unverified. No cross-platform proof claimed.
- Only retained fixture/seeding script was committed locally. No public forge writes or push; ghdrop uploads are the expressly requested evidence publication.

Final cleanup: stopped only the Electron/Xvfb session launched for this capture task and closed the task-created preview tab. CDP port 22369 is closed. Shared sshd PID 838816 remains listening on 22269 for lead cleanup. Tracked diff remains empty; runtime matches f472495255; final local HEAD eaeb2149b380fc54b2414e9a747d1ecfd1a6e96c.

## S1 narration supplement provenance

Only this evidence copy and captioned video derivatives were added for the narration proof gap; all original links, qualifications, and runtime/commit hashes above are preserved verbatim. No implementation changes, server/browser sessions, push, or public forge writes were performed for this supplement. FRICTION: none; inspection and captioning used local ffmpeg frames. Owned inspection scratch files were removed; outputs remain for lead cleanup.

SHA-256:

- `evidence-index.md`: `0e83a1d959c42c89b4860097fb055fbea507bff1d03e8b5d47cc0a34504e9cea`
- `before-S1-open.mp4`: `df4b9110728845ea72292598a7edaaecd5c48eff01152414b0edd476b9a44a18`
- `after-S1-open.mp4`: `cb823a08f7bc5c32e1605a75de3f509badbfdf8fb1a70d7c7dc77721e1180a1e`
- `before-S1-open-captioned.mp4`: `7769e9ee72f6294a6b20fb3e88336de7a332627ea9512fcd52ac37045ad692b6`
- `after-S1-open-captioned.mp4`: `a103c173eeaaf50813955a334b75ce713d2e8d7a97d4ad2de249e2586d0916e8`
