Settings: see and change which account you log in as on each host (D336, D229, D231, D319) #336

Open
opened 2026-11-04 03:39:16 +00:00 by kayg · 8 comments
Owner

J166 (design sub-agent, UI plus thin wiring). Owner, D336 (2026-11-04): "we also adjacently need some UI around what user one prefers on hosts as I wouldnt want to login as root all the time".

Task: a clear place to see and change which account you log in as on each host. Shows the current account ("You log in as kayg"), offers the accounts the host allows for you (root marked, never the default if a non-root option exists), applies to new terminals only (existing ones keep theirs), server is the authority, reuse the existing action (D318), not a passkey-per-action item (D333).

Branch: preferred-login-ui-j166, base origin/dev 109e14cb7.

Plan (first pass, ~3 h):

  1. Read what the backend stores / offers (accounts.rs, bootstrap_remote.rs confirm_preferred_login, websocket.rs prepare_preferred_login, session-ui.on-demand.ts) and what D319 name matching does.
  2. Pick the home (machine card vs Settings → Hosts) against the approved #304 Settings layout and TASTE; post the reasoning here.
  3. Implement UI on shared packages/ui rows; thin wiring to the existing action; add an action only if none fits.
  4. Playwright specs at 1440×900 and 393×852 (alignment ±0.5 px), production-build screenshots desktop/phone × dark/light.
  5. Real-environment check on test.ssh.kayg.org (needs the orchestrator to deploy the branch; enrolling a host is part of it) or a local real server.
  6. scripts/verify fast verbatim with head SHA.

Questions will be posted here with my recommendation; I continue on the safe default.

**J166 (design sub-agent, UI plus thin wiring).** Owner, D336 (2026-11-04): "we also adjacently need some UI around what user one prefers on hosts as I wouldnt want to login as root all the time". Task: a clear place to see and change which account *you* log in as on each host. Shows the current account ("You log in as kayg"), offers the accounts the host allows for you (root marked, never the default if a non-root option exists), applies to new terminals only (existing ones keep theirs), server is the authority, reuse the existing action (D318), not a passkey-per-action item (D333). Branch: `preferred-login-ui-j166`, base `origin/dev` 109e14cb7. Plan (first pass, ~3 h): 1. Read what the backend stores / offers (accounts.rs, bootstrap_remote.rs confirm_preferred_login, websocket.rs prepare_preferred_login, session-ui.on-demand.ts) and what D319 name matching does. 2. Pick the home (machine card vs Settings → Hosts) against the approved #304 Settings layout and TASTE; post the reasoning here. 3. Implement UI on shared `packages/ui` rows; thin wiring to the existing action; add an action only if none fits. 4. Playwright specs at 1440×900 and 393×852 (alignment ±0.5 px), production-build screenshots desktop/phone × dark/light. 5. Real-environment check on test.ssh.kayg.org (needs the orchestrator to deploy the branch; enrolling a host is part of it) or a local real server. 6. `scripts/verify fast` verbatim with head SHA. Questions will be posted here with my recommendation; I continue on the safe default.
Author
Owner

Start: branch preferred-login-ui-j166, base origin/dev 109e14cb7 (worktree ~/Developer/Worktrees/infraternal-j166 on the control host)

Findings (evidence in code, nothing run yet)

What is stored. Migration 0032_preferred_accounts.sql: preferred_accounts(user_id, account) is the person's global account (absent row = the person's infraternal username, D231); preferred_host_accounts(user_id, host_id, account) is the per-host override (empty host id = the server's own host). Accounts are names, never uids (valid_account in crates/plugins/ssh/src/accounts.rs).

The action already exists on the one route. ssh-accounts.get and ssh-accounts.set (Permission::One("authenticated"), Effect Read / Write) run on the WebSocket control stream; the browser already has Connection.call(actionId, input) (apps/tracer/src/connection.ts:338). The handler (crates/infraternal-server/src/preferred_accounts.rs) rechecks a live, unlocked session and, for a host id, that the person owns the host (remote_hosts.owner_id, not revoked), inside the writer transaction. get and set both return {account, global_account, host_account}. Nothing in apps/ or packages/ui calls it today (grep: no UI at all).

Where it is chosen today. Nowhere in the UI. Add-host does not ask: bootstrap_remote.rs::completed resolves the preferred account and confirm_preferred_login proves it opens on the new host. Terminal opens resolve it again (websocket.rs::open_terminal → preferred_accounts::resolve). Only the CLI adapter can set it.

What the host does with the name (crates/infraternal-agent/src/{daemon.rs,logins.rs}): a rootful agent opens the named account if it exists, else root with the note "No user X here, opened as root" (D231). A rootless agent can open only the account it runs as; any other name is refused (NoMatchingLogin / OtherAccount). So with the default (your infraternal name) a rootless host whose agent user has another name refuses every terminal until a per-host account is set. That refusal is the case D336 wants UI for.

D319 name matching is a decision only: grep finds no "names match people here" setting or code. Today the same-name rule is implicit (global default = username, hosts are owner-scoped). So "confirm once" has no screen yet.

Which accounts can a host offer? There is no API and the agent has no account listing. The server knows: the host's mode (remote_hosts.mode) and, for rootless hosts, the agent's user (user@ of the bootstrap address, shown as user in remote.host.list). It cannot know whether other accounts exist on a rootful host.

Decision for the home (reasoning)

Settings → Hosts, not the machine card:

  1. TASTE "Each flow has one home": a flow that changes something lives where it is managed (Settings), not in the quick card that summarises it. The card keeps its read-only "Login" fact.
  2. The refusal happens before a window exists on that host, so the fix cannot depend on an open window's card.
  3. It lists every machine you own, online or not, with no window open.
  4. The approved #304 rows (D323) have "Sign In As" under Machines › New Machines as the default; the per-machine list sits beside it as the same kind of row. On dev the flat Settings view still has the Hosts section, so it goes there now and moves with it.

Plan (about 4 h; I report at 8 h)

  1. Server, thin: ssh-accounts.get/set output gains choices (the accounts this host can offer you) and mode, computed from the host row: rootless → exactly the agent's user; rootful and the server's own host → your name, then root (marked). set refuses, for a rootless host, any account but its agent user (the agent would refuse it at every open anyway). Unit tests next to preferred_accounts_tests.rs.
  2. UI: a shared panel in packages/ui (rows are the shared settings rows): section "You log in as" in Settings → Hosts: first row the default for every machine, then one row per machine ("You log in as kayg"); pressing a row opens its choices in place (option rows, root marked, a tick on the current). One line says it applies to new terminals only; terminals already open keep their account.
  3. Wiring through connection.call; the mock harness gets a test double.
  4. Specs at 1440×900 and 393×852 (alignment ±0.5 px, worst-case fixtures), screenshots from a production build (desktop/phone × dark/light), real check on test.ssh.kayg.org (I will ask for the deploy once a branch head is pushed).

Question for the owner (default picked, moving on)

Should a host's agent list its real login accounts (a new agent action, about 3–4 h: agent arm + server relay + tests)? Without it a rootful host offers only your name and root, and a name that does not exist there still opens as root with the D231 note. Recommended: yes, as a follow-up job; this UI is data-driven and shows the longer list unchanged. Default now: no agent change.

## Start: branch `preferred-login-ui-j166`, base `origin/dev` 109e14cb7 (worktree `~/Developer/Worktrees/infraternal-j166` on the control host) ## Findings (evidence in code, nothing run yet) **What is stored.** Migration `0032_preferred_accounts.sql`: `preferred_accounts(user_id, account)` is the person's global account (absent row = the person's infraternal username, D231); `preferred_host_accounts(user_id, host_id, account)` is the per-host override (empty host id = the server's own host). Accounts are names, never uids (`valid_account` in `crates/plugins/ssh/src/accounts.rs`). **The action already exists on the one route.** `ssh-accounts.get` and `ssh-accounts.set` (`Permission::One("authenticated")`, Effect Read / Write) run on the WebSocket control stream; the browser already has `Connection.call(actionId, input)` (`apps/tracer/src/connection.ts:338`). The handler (`crates/infraternal-server/src/preferred_accounts.rs`) rechecks a live, unlocked session and, for a host id, that the person owns the host (`remote_hosts.owner_id`, not revoked), inside the writer transaction. `get` and `set` both return `{account, global_account, host_account}`. Nothing in `apps/` or `packages/ui` calls it today (grep: no UI at all). **Where it is chosen today.** Nowhere in the UI. Add-host does not ask: `bootstrap_remote.rs::completed` resolves the preferred account and `confirm_preferred_login` proves it opens on the new host. Terminal opens resolve it again (`websocket.rs::open_terminal` → `preferred_accounts::resolve`). Only the CLI adapter can set it. **What the host does with the name** (`crates/infraternal-agent/src/{daemon.rs,logins.rs}`): a rootful agent opens the named account if it exists, else root with the note "No user X here, opened as root" (D231). A rootless agent can open **only the account it runs as**; any other name is refused (`NoMatchingLogin` / `OtherAccount`). So with the default (your infraternal name) a rootless host whose agent user has another name refuses every terminal until a per-host account is set. That refusal is the case D336 wants UI for. **D319 name matching** is a decision only: grep finds no "names match people here" setting or code. Today the same-name rule is implicit (global default = username, hosts are owner-scoped). So "confirm once" has no screen yet. **Which accounts can a host offer?** There is no API and the agent has no account listing. The server knows: the host's mode (`remote_hosts.mode`) and, for rootless hosts, the agent's user (`user@` of the bootstrap address, shown as `user` in `remote.host.list`). It cannot know whether other accounts exist on a rootful host. ## Decision for the home (reasoning) **Settings → Hosts**, not the machine card: 1. TASTE "Each flow has one home": a flow that changes something lives where it is managed (Settings), not in the quick card that summarises it. The card keeps its read-only "Login" fact. 2. The refusal happens before a window exists on that host, so the fix cannot depend on an open window's card. 3. It lists every machine you own, online or not, with no window open. 4. The approved #304 rows (D323) have "Sign In As" under Machines › New Machines as the *default*; the per-machine list sits beside it as the same kind of row. On dev the flat Settings view still has the Hosts section, so it goes there now and moves with it. ## Plan (about 4 h; I report at 8 h) 1. **Server, thin:** `ssh-accounts.get/set` output gains `choices` (the accounts this host can offer you) and `mode`, computed from the host row: rootless → exactly the agent's user; rootful and the server's own host → your name, then root (marked). `set` refuses, for a rootless host, any account but its agent user (the agent would refuse it at every open anyway). Unit tests next to `preferred_accounts_tests.rs`. 2. **UI:** a shared panel in `packages/ui` (rows are the shared settings rows): section "You log in as" in Settings → Hosts: first row the default for every machine, then one row per machine ("You log in as kayg"); pressing a row opens its choices in place (option rows, root marked, a tick on the current). One line says it applies to new terminals only; terminals already open keep their account. 3. Wiring through `connection.call`; the mock harness gets a test double. 4. Specs at 1440×900 and 393×852 (alignment ±0.5 px, worst-case fixtures), screenshots from a production build (desktop/phone × dark/light), real check on test.ssh.kayg.org (I will ask for the deploy once a branch head is pushed). ## Question for the owner (default picked, moving on) Should a host's agent list its real login accounts (a new agent action, about 3–4 h: agent arm + server relay + tests)? Without it a rootful host offers only your name and root, and a name that does not exist there still opens as root with the D231 note. Recommended: yes, as a follow-up job; this UI is data-driven and shows the longer list unchanged. Default now: no agent change.
Author
Owner

Progress (head 232a49414 on preferred-login-ui-j166, six atomic commits on origin/dev 109e14cb7, all pushed)

Done, not yet run on a VM (waiting for a build slot; verify quick is queued on dev-02, log ~/j166-logs/quick2.log):

  1. server: ssh-accounts.get/set now also return mode, choices (your name first, root marked and last), works and you; set refuses any account but the agent's own on a rootless host. Three new server tests.
  2. ui: option list + heading moved to packages/ui/src/settings-rows.ts (pure code motion).
  3. ui: packages/ui/src/login-accounts.ts + styles: Settings → Hosts, section "You log in as" (default row, then one row per machine; press a row, its accounts open in place; amber "Choose an account" when the default cannot open there).
  4. tracer: adapter over connection.call (apps/tracer/src/canvas/sessions/login-accounts.ts, built by the on-demand Settings body), mock server double (?mock=1&logins=1|many), unit test, Playwright spec test/login-accounts.spec.ts (1440×900 + 393×852, ink + paper), palette row "Settings: Account you log in as".
  5. fmt failure from the first verify quick fixed by cargo fmt, squashed into the server commit.

Next: tsc, unit tests, the Playwright spec and screenshots (production tracer build), verify quick/fast, then the real check. Request to the orchestrator: once fast is green I will ask for the branch to be deployed to https://test.ssh.kayg.org; the Rust change (the new fields) is what the real check proves.

## Progress (head `232a49414` on `preferred-login-ui-j166`, six atomic commits on `origin/dev` 109e14cb7, all pushed) Done, not yet run on a VM (waiting for a build slot; `verify quick` is queued on dev-02, log `~/j166-logs/quick2.log`): 1. `server:` `ssh-accounts.get/set` now also return `mode`, `choices` (your name first, root marked and last), `works` and `you`; `set` refuses any account but the agent's own on a rootless host. Three new server tests. 2. `ui:` option list + heading moved to `packages/ui/src/settings-rows.ts` (pure code motion). 3. `ui:` `packages/ui/src/login-accounts.ts` + styles: Settings → Hosts, section "You log in as" (default row, then one row per machine; press a row, its accounts open in place; amber "Choose an account" when the default cannot open there). 4. `tracer:` adapter over `connection.call` (`apps/tracer/src/canvas/sessions/login-accounts.ts`, built by the on-demand Settings body), mock server double (`?mock=1&logins=1|many`), unit test, Playwright spec `test/login-accounts.spec.ts` (1440×900 + 393×852, ink + paper), palette row "Settings: Account you log in as". 5. `fmt` failure from the first `verify quick` fixed by cargo fmt, squashed into the server commit. Next: `tsc`, unit tests, the Playwright spec and screenshots (production tracer build), `verify quick`/`fast`, then the real check. **Request to the orchestrator:** once `fast` is green I will ask for the branch to be deployed to https://test.ssh.kayg.org; the Rust change (the new fields) is what the real check proves.
Author
Owner

Request to the orchestrator: deploy preferred-login-ui-j166 to https://test.ssh.kayg.org, and a machine to enroll

Head to deploy: the current head of origin/preferred-login-ui-j166 (232a49414 now; I will say here if it moves before you deploy). The Rust change (ssh-accounts.get/set answer with choices, mode, works, you) is final unless review changes it; the UI is still being checked on a production tracer build.

What the real check needs, in order of value:

  1. A rootless host enrolled on the test server (an agent running as an ordinary account such as deploy, enrolled through add-host). That is the case D336 is about: your infraternal name has no account there, so every terminal is refused until you choose, and the screen must show "Choose an account" and let me fix it, then a new terminal must open as that account. I do not have a login for any machine the test server can reach, and I must not print or copy secrets, so I cannot enroll one myself. If you can enroll one (or tell me which machine and which add-host credential I may use, by name only), I will drive the rest through test-admin-signin.ts.
  2. The server's own host (already there): default row, "this server" row, root marked, choose and revert, with a terminal opened before and after the change to show the old one keeps its account.

Safe default if (1) is too costly: I prove the Rust and wire path on a local real server on compute01 (real binary, real SQLite, real WebSocket and action route, a rootless host row inserted in the database) and say plainly that the rootless agent itself was not enrolled. I will start that now and report which one I did.

## Request to the orchestrator: deploy `preferred-login-ui-j166` to https://test.ssh.kayg.org, and a machine to enroll Head to deploy: the current head of `origin/preferred-login-ui-j166` (232a49414 now; I will say here if it moves before you deploy). The Rust change (`ssh-accounts.get/set` answer with `choices`, `mode`, `works`, `you`) is final unless review changes it; the UI is still being checked on a production tracer build. What the real check needs, in order of value: 1. **A rootless host enrolled on the test server** (an agent running as an ordinary account such as `deploy`, enrolled through add-host). That is the case D336 is about: your infraternal name has no account there, so every terminal is refused until you choose, and the screen must show "Choose an account" and let me fix it, then a new terminal must open as that account. I do not have a login for any machine the test server can reach, and I must not print or copy secrets, so I cannot enroll one myself. If you can enroll one (or tell me which machine and which add-host credential I may use, by name only), I will drive the rest through `test-admin-signin.ts`. 2. The server's own host (already there): default row, "this server" row, root marked, choose and revert, with a terminal opened before and after the change to show the old one keeps its account. **Safe default if (1) is too costly:** I prove the Rust and wire path on a local real server on compute01 (real binary, real SQLite, real WebSocket and action route, a rootless host row inserted in the database) and say plainly that the rootless agent itself was not enrolled. I will start that now and report which one I did.
Author
Owner

Progress: history cleaned, head e7739e5dd (six logical commits on origin/dev)

fb139c685 server · 6e74a15bc ui (pure code motion) · d0033f6ff ui panel · f7635943e tracer wiring + mock + specs · 0b2ff277c palette · e7739e5dd real-server spec. Rebuilt from the tested tree (byte-identical apart from a DECISIONS.md change that landed on dev meanwhile).

Results so far (dev-02, production tracer build, headless Chromium):

  • verify quick on the first server commit set: fmt, clippy and the changed-package unit tests ran; all 6 preferred_accounts tests passed; one unrelated test failed, websocket::writer_tests::authority_watchdog::cap_review_r3::sqlite_busy_timeout_recovers_detached_storm_without_unlocking ("socket test stopped before its observed event", a wall-clock watchdog test, 3 of 4 gates ran with other jobs' gates on the VM). Run alone on the same build: test result: ok. 1 passed; 0 failed in 2.97 s. I touched no code it reads.
  • tsc clean; 8 unit tests for the adapter pass.
  • test/login-accounts.spec.ts + settings-edges + settings-rows: the behaviour, failed-save, palette and fleet specs pass at 1440×900 and 393×852. Layout alignment found three things, all fixed: names were 0.57 px off their mark's centre (shared line height; fixed with line-height: normal, measured 0.00 now), a measurement used clientWidth (rounded to a whole pixel) and an svg path's client rect (includes the stroke under the canvas camera's scale) so it now measures against the row's own right edge and the svg box, and the layout test read rows below the window's fold before they were scrolled to (by design a row asks for its state only when near the screen).
  • Queued on dev-02: the browser specs on this head and scripts/verify fast. Queued on compute01: the root run (the server's own-host rule has a root-only branch, D229) and the real-server spec.

Still waiting on you (orchestrator): the deploy to test.ssh.kayg.org and an enrolled host, see my earlier comment.

## Progress: history cleaned, head `e7739e5dd` (six logical commits on `origin/dev`) `fb139c685` server · `6e74a15bc` ui (pure code motion) · `d0033f6ff` ui panel · `f7635943e` tracer wiring + mock + specs · `0b2ff277c` palette · `e7739e5dd` real-server spec. Rebuilt from the tested tree (byte-identical apart from a `DECISIONS.md` change that landed on dev meanwhile). Results so far (dev-02, production tracer build, headless Chromium): - `verify quick` on the first server commit set: fmt, clippy and the changed-package unit tests ran; **all 6 `preferred_accounts` tests passed**; one unrelated test failed, `websocket::writer_tests::authority_watchdog::cap_review_r3::sqlite_busy_timeout_recovers_detached_storm_without_unlocking` ("socket test stopped before its observed event", a wall-clock watchdog test, 3 of 4 gates ran with other jobs' gates on the VM). Run alone on the same build: `test result: ok. 1 passed; 0 failed` in 2.97 s. I touched no code it reads. - `tsc` clean; 8 unit tests for the adapter pass. - `test/login-accounts.spec.ts` + `settings-edges` + `settings-rows`: the behaviour, failed-save, palette and fleet specs pass at 1440×900 and 393×852. Layout alignment found three things, all fixed: names were 0.57 px off their mark's centre (shared line height; fixed with `line-height: normal`, measured 0.00 now), a measurement used `clientWidth` (rounded to a whole pixel) and an svg path's client rect (includes the stroke under the canvas camera's scale) so it now measures against the row's own right edge and the svg box, and the layout test read rows below the window's fold before they were scrolled to (by design a row asks for its state only when near the screen). - Queued on dev-02: the browser specs on this head and `scripts/verify fast`. Queued on compute01: the root run (the server's own-host rule has a root-only branch, D229) and the real-server spec. Still waiting on you (orchestrator): the deploy to test.ssh.kayg.org and an enrolled host, see my earlier comment.
Author
Owner

Status (head 4afe1ec84, pushed): waiting on VM build slots, nothing else blocks

Findings since the last comment, with evidence:

  1. Root run on compute01 (root, throwaway clone /root/j166), first head 5c1d256d3 (same Rust as now): preferred_accounts unit tests 9 passed, 0 failed, including the_servers_own_host_offers_what_its_embedded_agent_can_open, whose root branch only runs as root (root server: your name first, root marked and last, works: true). The real-server spec ran as root on the real binary and drew the section ("You log in as", "Every machine", and the server's own host row, infraternal-dev-01-compute01); it failed only because my fixture did not enable remote hosts (remoteListen), fixed in the spec.
  2. Pixel proof of alignment (the spec's geometric chevron check was the problem, not the layout): decoding the 1440×900 @2× screenshots, the rightmost drawn column of the chevrons and of the Extended-info switch is x=967 in both the real-server and the mock screenshot. The spec now measures rendered pixels (inkRight) instead of boxes and paths.
  3. Two real bugs the specs caught, fixed: a failed save wrote its message into a body that a re-read had already rebuilt (the message was lost); the open list was rebuilt on every re-read, which would drop keyboard focus. Also: a failed save for a row already closed no longer refills its body.
  4. scripts/verify fast, first run, head e7739e5dd (dev-02, load average ~15): all rows PASS except test, which failed 9 of 11 agent_daemon tests ("rootless explicit-state preparation refused" after a read timeout in scripts/agent_fixture.py). Rerun alone on the same build: test result: ok. 11 passed; 0 failed in 56 s at load ~7. These tests spawn real agents and read with short timeouts; I touch nothing they run. I will rerun the full gate on the final head.
  5. Audit: contracts/plugin.md §4 says every call is audited, but the server has no audit sink in code yet (grep audit finds only test names). ssh-accounts.set therefore has no audit entry today, like every other action; no per-action code was added (nothing to hook, and the shared dispatch is the place).

Queued on dev-02 (positions 1 and 2): job A (tsc, unit, browser specs on a production build, real-server spec as non-root) and verify fast; on compute01: the root run on the final head. Still no reply on the deploy/host request, so the real check is the local real server (as root and as non-root) unless you answer.

## Status (head `4afe1ec84`, pushed): waiting on VM build slots, nothing else blocks Findings since the last comment, with evidence: 1. **Root run on compute01 (root, throwaway clone `/root/j166`)**, first head `5c1d256d3` (same Rust as now): `preferred_accounts` unit tests **9 passed, 0 failed**, including `the_servers_own_host_offers_what_its_embedded_agent_can_open`, whose root branch only runs as root (root server: your name first, root marked and last, `works: true`). The real-server spec ran as root on the real binary and drew the section ("You log in as", "Every machine", and the server's own host row, `infraternal-dev-01-compute01`); it failed only because my fixture did not enable remote hosts (`remoteListen`), fixed in the spec. 2. **Pixel proof of alignment** (the spec's geometric chevron check was the problem, not the layout): decoding the 1440×900 @2× screenshots, the rightmost drawn column of the chevrons and of the Extended-info switch is x=967 in both the real-server and the mock screenshot. The spec now measures rendered pixels (`inkRight`) instead of boxes and paths. 3. **Two real bugs the specs caught, fixed:** a failed save wrote its message into a body that a re-read had already rebuilt (the message was lost); the open list was rebuilt on every re-read, which would drop keyboard focus. Also: a failed save for a row already closed no longer refills its body. 4. **`scripts/verify fast`, first run, head `e7739e5dd`** (dev-02, load average ~15): all rows PASS except `test`, which failed 9 of 11 `agent_daemon` tests ("rootless explicit-state preparation refused" after a read timeout in `scripts/agent_fixture.py`). Rerun alone on the same build: `test result: ok. 11 passed; 0 failed` in 56 s at load ~7. These tests spawn real agents and read with short timeouts; I touch nothing they run. I will rerun the full gate on the final head. 5. **Audit:** `contracts/plugin.md §4` says every call is audited, but the server has no audit sink in code yet (`grep audit` finds only test names). `ssh-accounts.set` therefore has no audit entry today, like every other action; no per-action code was added (nothing to hook, and the shared dispatch is the place). Queued on dev-02 (positions 1 and 2): job A (tsc, unit, browser specs on a production build, real-server spec as non-root) and `verify fast`; on compute01: the root run on the final head. Still no reply on the deploy/host request, so the real check is the local real server (as root and as non-root) unless you answer.
Author
Owner

Screenshots: production tracer build (headless Chromium on dev-02, browser run PW_EXIT=0, 21 specs passed)

closed-*, open-rootful-* (your name first, root marked), open-rootless-* (one account, reason, amber "Choose an account"), long-name-*; ink and paper, 1440×900 @2× and 393×852 @3×. Taken from the mock server double; the real-server screenshots follow with job B.

## Screenshots: production tracer build (headless Chromium on dev-02, browser run `PW_EXIT=0`, 21 specs passed) `closed-*`, `open-rootful-*` (your name first, root marked), `open-rootless-*` (one account, reason, amber "Choose an account"), `long-name-*`; ink and paper, 1440×900 @2× and 393×852 @3×. Taken from the mock server double; the real-server screenshots follow with job B.
Author
Owner

Status (head acff57239, on origin/dev 5d33f7cdd): code done; two confirming runs still queued

Done and evidenced

  • Browser run on a production tracer build (dev-02), head bb743a499 (same UI as now): tsc clean, 8 adapter unit tests pass, 21 Playwright specs passed (login-accounts ×10 at 1440×900 and 393×852 in ink and paper, settings-edges ×4, settings-rows ×7): alignment ±0.5 px (names on one centre line with their marks, chevrons ending on the same pixel column as the Extended-info switch, measured from rendered pixels), root marked/last, rootless host offering one account, failed save, Escape, one row open at a time, fleet of 64 with an unbreakable name, palette finds "log in as". Screenshots attached above (comment 77572).
  • As root on compute01 (throwaway clone, /root/j166): preferred_accounts 9 passed, 0 failed, twice, including the root-only own-host branch.
  • Server: ssh-accounts.get/set reply now carries mode, choices, works, you; the existing action and route, same permission, no new action. Not a per-action passkey item (D333). Audit: see my earlier note (no audit sink exists in code yet).

Not yet green, and why (honest)

  • scripts/verify fast has not passed on any head: run 1 (e7739e5dd): only test failed, 9 of 11 agent_daemon tests (load; 11/11 alone); run 2 (4afe1ec84): only test, vt_credit credit probe (open #118; passes alone, 1 passed); runs 3 and 4 failed every cargo row with cannot update the lock file ... because --locked: origin/dev itself was inconsistent for a while (stale qrcodegen entry in Cargo.lock, my branch touches no manifest or lock); current dev builds again (the locked build compiled on pristine origin/dev 1c381d18d). A fifth run on the current head is queued (dev-02, position 5).
  • The real-server spec (production binary, real SQLite and action route) got as far as: setup, unlock, seeded rootless host build-01 listed with "Choose an account" (real server, non-root run), then failed on timing: rows below the fold load lazily and the spec did not scroll to them. Fixed in acff57239; queued as job B on dev-02 (position 4). The root run of it failed on the same thing, not yet rerun.
  • compute01 fell below the 25 GB floor for a while (build-slot waited), caused by other jobs' targets (78 GB j132b, 64 GB j61c, ...), not mine (mine is 8 GB).

No answer yet on the test.ssh.kayg.org deploy and an enrollable host. If either queued run fails for a reason of mine I will fix it; otherwise I report with the head SHA and the verbatim gate output when they finish.

## Status (head `acff57239`, on `origin/dev` 5d33f7cdd): code done; two confirming runs still queued **Done and evidenced** - Browser run on a production tracer build (dev-02), head `bb743a499` (same UI as now): `tsc` clean, 8 adapter unit tests pass, **21 Playwright specs passed** (`login-accounts` ×10 at 1440×900 and 393×852 in ink and paper, `settings-edges` ×4, `settings-rows` ×7): alignment ±0.5 px (names on one centre line with their marks, chevrons ending on the same pixel column as the Extended-info switch, measured from rendered pixels), root marked/last, rootless host offering one account, failed save, Escape, one row open at a time, fleet of 64 with an unbreakable name, palette finds "log in as". Screenshots attached above (comment 77572). - As root on compute01 (throwaway clone, `/root/j166`): `preferred_accounts` **9 passed, 0 failed**, twice, including the root-only own-host branch. - Server: `ssh-accounts.get/set` reply now carries `mode`, `choices`, `works`, `you`; the existing action and route, same permission, no new action. Not a per-action passkey item (D333). Audit: see my earlier note (no audit sink exists in code yet). **Not yet green, and why (honest)** - `scripts/verify fast` has not passed on any head: run 1 (`e7739e5dd`): only `test` failed, 9 of 11 `agent_daemon` tests (load; 11/11 alone); run 2 (`4afe1ec84`): only `test`, `vt_credit` credit probe (open #118; passes alone, 1 passed); runs 3 and 4 failed every cargo row with `cannot update the lock file ... because --locked`: `origin/dev` itself was inconsistent for a while (stale `qrcodegen` entry in `Cargo.lock`, my branch touches no manifest or lock); current dev builds again (the locked build compiled on pristine `origin/dev` 1c381d18d). A fifth run on the current head is queued (dev-02, position 5). - The real-server spec (production binary, real SQLite and action route) got as far as: setup, unlock, seeded rootless host `build-01` listed with "Choose an account" (real server, non-root run), then failed on timing: rows below the fold load lazily and the spec did not scroll to them. Fixed in `acff57239`; queued as job B on dev-02 (position 4). The root run of it failed on the same thing, not yet rerun. - compute01 fell below the 25 GB floor for a while (`build-slot` waited), caused by other jobs' targets (78 GB `j132b`, 64 GB `j61c`, ...), not mine (mine is 8 GB). No answer yet on the test.ssh.kayg.org deploy and an enrollable host. If either queued run fails for a reason of mine I will fix it; otherwise I report with the head SHA and the verbatim gate output when they finish.
Author
Owner

Finish (stopped at ~8 h, past 2× my estimate): head 3c0d80598 on preferred-login-ui-j166, base origin/dev a89ebb0ae

Correction first. My earlier history rebuilds (heads e7739e5dd … acff57239) copied whole directories from my old snapshot (git checkout F -- crates), which silently reverted other people's newer changes under crates/, packages/ and apps/ on top of newer origin/dev. That is what broke every cargo --locked row in gate runs 3–5 and job B (it reverted crates/infraternal/Cargo.toml); it was my bug, not dev's (my statement above that dev's lockfile was inconsistent is withdrawn). 3c0d80598 is rebuilt by applying only my own diffs: git diff --name-only origin/dev HEAD lists exactly my 17 files, whose content is byte-identical to the tree that passed the browser run.

Commits (six, atomic): 4548656ec server (ssh-accounts.get/set answer with mode, choices, works, you; rootless remote hosts refuse any account but the agent's own; the server's own host follows its effective uid) · bab7a197f ui (pure code motion: shared option list) · c5389a4cc ui panel (Settings → Hosts, "You log in as") · fa53ae87a tracer wiring, mock double, specs · 0c2bee0f7 palette · 3c0d80598 real-server spec.

Evidence that exists

  • Browser run on a production tracer build, dev-02, UI identical to the head: tsc clean, 8 unit tests, 21/21 Playwright passed (login-accounts ×10, settings-edges ×4, settings-rows ×7), 1440×900 and 393×852, ink and paper. Screenshots: comment 77572.
  • As root (compute01, throwaway clone, cleaned up): preferred_accounts 9 passed, 0 failed (twice), including the root-only branch.
  • Real server (production binary, real SQLite, real WebSocket and action route), non-root run: after unlocking host connections the seeded rootless host build-01 appeared with "Choose an account" and the real server's own host row showed the account. Pixel measurement of the real and mock screenshots: chevrons and the switch end on the same pixel column.
  • Bugs the specs found and I fixed: lost failure line after a re-read, list rebuilt on every re-read (focus loss), redraw on every sessions change (rows unclickable on a real server), failed save for a closed row.

What is NOT proven on this head (please read)

  • scripts/verify fast is not green on any head. Run 1 (e7739e5dd): only test failed, 9 of 11 agent_daemon tests (load average ~15; 11/11 alone). Run 2 (4afe1ec84): only test, vt_credit (open #118; passes alone). Runs 3–5 failed on my rebuild bug above. I have not run fast on 3c0d80598. verify quick on the first server commit set: fmt and clippy passed, 6 new preferred_accounts tests passed, one unrelated watchdog test failed under load and passed alone.
  • The real-server spec has not passed end to end: it was last fixed (rows below the fold load lazily, so it scrolls to them) but the final run failed on the broken build. Not rerun.
  • No run on test.ssh.kayg.org: no reply to the deploy request, and no enrolled rootless host exists. The real check was local.
  • No agent-side account listing: a rootful host offers your name and root only (a missing name falls back to root with the D231 note). Needs your decision: build an agent action that lists real login accounts (3–4 h)? Recommended yes.
  • Audit: the server has no audit sink in code, so ssh-accounts.set is not audited, like every action (contract §4 promises one).
  • Settings → Hosts is the home (TASTE: each flow has one home); it moves into Machines › New Machines with J132's rows. Say if you want it on the machine card as well.

Queued jobs cancelled, targets deleted on both VMs, leftover shims killed. To finish: scripts/verify fast on 3c0d80598 and bun x playwright test -c playwright.real.config.ts real/login-accounts.spec.ts with a built server binary.

## Finish (stopped at ~8 h, past 2× my estimate): head `3c0d80598` on `preferred-login-ui-j166`, base `origin/dev` a89ebb0ae **Correction first.** My earlier history rebuilds (heads `e7739e5dd` … `acff57239`) copied whole directories from my old snapshot (`git checkout F -- crates`), which silently reverted other people's newer changes under `crates/`, `packages/` and `apps/` on top of newer `origin/dev`. That is what broke every `cargo --locked` row in gate runs 3–5 and job B (it reverted `crates/infraternal/Cargo.toml`); it was **my** bug, not dev's (my statement above that dev's lockfile was inconsistent is withdrawn). `3c0d80598` is rebuilt by applying only my own diffs: `git diff --name-only origin/dev HEAD` lists exactly my 17 files, whose content is byte-identical to the tree that passed the browser run. **Commits (six, atomic):** `4548656ec` server (`ssh-accounts.get/set` answer with `mode`, `choices`, `works`, `you`; rootless remote hosts refuse any account but the agent's own; the server's own host follows its effective uid) · `bab7a197f` ui (pure code motion: shared option list) · `c5389a4cc` ui panel (Settings → Hosts, "You log in as") · `fa53ae87a` tracer wiring, mock double, specs · `0c2bee0f7` palette · `3c0d80598` real-server spec. **Evidence that exists** - Browser run on a production tracer build, dev-02, UI identical to the head: `tsc` clean, 8 unit tests, **21/21 Playwright passed** (login-accounts ×10, settings-edges ×4, settings-rows ×7), 1440×900 and 393×852, ink and paper. Screenshots: comment 77572. - As root (compute01, throwaway clone, cleaned up): `preferred_accounts` **9 passed, 0 failed** (twice), including the root-only branch. - Real server (production binary, real SQLite, real WebSocket and action route), non-root run: after unlocking host connections the seeded rootless host `build-01` appeared with "Choose an account" and the real server's own host row showed the account. Pixel measurement of the real and mock screenshots: chevrons and the switch end on the same pixel column. - Bugs the specs found and I fixed: lost failure line after a re-read, list rebuilt on every re-read (focus loss), redraw on every sessions change (rows unclickable on a real server), failed save for a closed row. **What is NOT proven on this head (please read)** - **`scripts/verify fast` is not green on any head.** Run 1 (`e7739e5dd`): only `test` failed, 9 of 11 `agent_daemon` tests (load average ~15; 11/11 alone). Run 2 (`4afe1ec84`): only `test`, `vt_credit` (open #118; passes alone). Runs 3–5 failed on my rebuild bug above. **I have not run `fast` on `3c0d80598`.** `verify quick` on the first server commit set: fmt and clippy passed, 6 new `preferred_accounts` tests passed, one unrelated watchdog test failed under load and passed alone. - The real-server spec has not passed end to end: it was last fixed (rows below the fold load lazily, so it scrolls to them) but the final run failed on the broken build. Not rerun. - **No run on test.ssh.kayg.org**: no reply to the deploy request, and no enrolled rootless host exists. The real check was local. - **No agent-side account listing**: a rootful host offers your name and root only (a missing name falls back to root with the D231 note). Needs your decision: build an agent action that lists real login accounts (3–4 h)? Recommended yes. - Audit: the server has no audit sink in code, so `ssh-accounts.set` is not audited, like every action (contract §4 promises one). - Settings → Hosts is the home (TASTE: each flow has one home); it moves into Machines › New Machines with J132's rows. Say if you want it on the machine card as well. Queued jobs cancelled, targets deleted on both VMs, leftover shims killed. To finish: `scripts/verify fast` on `3c0d80598` and `bun x playwright test -c playwright.real.config.ts real/login-accounts.spec.ts` with a built server binary.
Sign in to join this conversation.
No labels
launch-qa
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal#336
No description provided.