fix(auth): a tab acts only as the account it was built for, and the review's other findings

A tab names the account it was claimed for on every request, beacon and upload
(X-Siftlode-Expect-Account); current_user and /auth/logout refuse a mismatch with
401 account_changed and keep the session, so a tab left showing the account
signed in before reloads instead of writing to the new one.

/auth/login clears a connect marker left by an abandoned connect, and a link
completes only on a session that still holds. The prefs merge reads the row
under a lock. A tab's sessionStorage records its own owner. A page the account
loses is given up, address bar and remembered page included. The panel layouts
are preferences; the storage contract also refuses a key handed to the Storage
API or to usePref outside its kind. A refused sign-in as someone else and a
failed sign-out say so. The chromium-only e2e specs are in the gate register,
the member walk waits for its requests, and devices.spec checks the save itself.
This commit is contained in:
2026-10-21 01:05:12 +02:00
parent 28b77fed1e
commit 94418a087e
39 changed files with 576 additions and 78 deletions
+2 -1
View File
@@ -107,7 +107,8 @@ project checks needs a row.
| Scope | Narrowed | Why | Measured |
| --- | --- | --- | --- |
| check | e2e (Playwright) not in `check` | It needs the :8080 stack built from the tree (minutes). It runs in `check-full`, and `release` rebuilds the stack and requires it (E32 D2) — nothing ships without it. | 5 specs × 3 engines |
| check | e2e (Playwright) not in `check` | It needs the :8080 stack built from the tree (minutes). It runs in `check-full`, and `release` rebuilds the stack and requires it (E32 D2) — nothing ships without it. | 9 specs: 6 × 3 engines, 3 on chromium only (the row below) |
| e2e | `a11y.spec.ts` `member.spec.ts` `devices.spec.ts` run on chromium only (`CHROMIUM_ONLY`, the webkit and ipad projects' `testIgnore`) | What they hold does not change with the engine: the axe scan reads the DOM and the accessibility tree, which the engines build alike; the member spec checks which pages and requests a role gets; the devices spec opens its own desktop and iPad contexts. Run three times they would triple their time and catch nothing more. What an engine does change (layout, events) the other specs hold on all three. | 3 of 9 specs |
| pushes | no server-side gate (no CI) | Owner decision 2026-10-04. The gate (`scripts/check.sh`) runs on the dev machine before work is handed over, and `release` runs it, then e2e, before anything is merged and Trivy before the image is pushed — the CI only repeated that, after the merge. Its runner shared the git host's container, and one run there starved Gitea of memory until it stopped answering. What it added — a fresh `npm ci` on Linux — the image build does at publish. | — |
| coverage | not in the gate; no threshold | Owner decision E32 D4: never enforced; "every regression test seen red" is the bar, and a percentage invites tests written to move it. Out of the lanes since E35: read once, by hand, it found 5 bugs; as a lane it was a number nobody acted on, and the slowest vitest run (the one that flaked). On demand: docs/development.md. | frontend 80% / backend 78% of lines (E32 S1) |
| CVE gate | HIGH/CRITICAL with a fix available only | `--ignore-unfixed` + `--severity HIGH,CRITICAL`: a finding with no fix cannot be acted on by an upgrade; it shows in the scan output. A fixable one fails the publish, and the only way past it is `.trivyignore.yaml`. | 0 open (E32 S1) |