From c99ef08cf16f0b11ceb14de1b1779a3291866962 Mon Sep 17 00:00:00 2001 From: "n.siegfried" Date: Wed, 5 Aug 2026 18:06:47 -0700 Subject: [PATCH] Record the smoketest auth gap and the browser-verification gap Two things surfaced while building the User Directory that are worth a decision rather than a mention in a handover. 3. server/smoketest.py has no login step, so auth_gate 401s every check after /api/health. DEPLOYMENT.md presents it as the way to prove the stack works end-to-end, including a docker compose exec invocation, so the documented verification path reports failure on a healthy system -- the failure mode most likely to be believed. Rated Medium for that reason. Predates the login portal; confirmed unrelated to this branch by stashing it and re-running. The Admin Console's in-browser smoke test is the working equivalent today. 4. users.js and wp-sidenav.js have never been executed -- no JS engine on the machine they were written on. Logged as a verification gap, not a defect, with what WAS checked (server tests, delimiter balance, handler resolution, id targets) and what only a browser can settle (layout, transitions, focus trap). Includes the five-step manual pass that closes it, and the hard-reload note, since sw.js bumped to wp-suite-shell-v6 and a soft reload serves the old shell. Both entries follow the file's existing shape: what is wrong, what it costs, why it is still open, what closing it takes. Co-Authored-By: Claude Opus 5 (1M context) --- KNOWN-ISSUES.md | 129 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/KNOWN-ISSUES.md b/KNOWN-ISSUES.md index 5f4952d..ede8208 100644 --- a/KNOWN-ISSUES.md +++ b/KNOWN-ISSUES.md @@ -12,6 +12,8 @@ Close an entry by deleting it in the same commit that fixes it. |---|-------|----------|--------|--------| | 1 | XSS via SOP discipline names in the WP creator | Medium (internal), High if externally reachable | 2026-08-05 | Open | | 2 | Archived projects: the two big apps don't grey out their own controls | Low | 2026-08-05 | Open | +| 3 | `server/smoketest.py` cannot authenticate — every run fails with 401 | Medium | 2026-08-05 | Open | +| 4 | User Directory and nav drawer have not been run in a browser | Low (verification gap, not a known defect) | 2026-08-05 | Open | --- @@ -161,3 +163,130 @@ save/issue controls, or add a boot check in each app that disables them and show read-only notice inline. Decide separately how the embedded creator (`wp-creation-index.html`) surfaces it, since it runs in an iframe where the shared app bar — and therefore the banner — is deliberately skipped. + +--- + +## 3. `server/smoketest.py` cannot authenticate — every run fails with 401 + +**Files:** `server/smoketest.py` · documented in `DEPLOYMENT.md` §"Automated smoke +test" (line ~147) +**Predates:** the login portal. The script was written against an open API and was +never updated when authentication landed. + +### What is wrong + +The script has no login step — no call to `/api/auth/login`, no cookie jar, no +credential arguments. `auth_gate` (`server/app.py`) refuses every `/api/` route +without a session cookie, so every check after the first fails: + +``` +- create project (status=401) +- fetch project by id (status=401) +... +Result: FAIL +``` + +Only `/api/health` passes, because it is on `auth._EXEMPT_EXACT`. + +### What it costs + +**The documented end-to-end verification path does not work, and hasn't for some +time.** `DEPLOYMENT.md` presents this as the way to prove "NGINX → FastAPI → +PostgreSQL all work", including a `docker compose exec` invocation for use inside the +api container. Anyone following it after a deploy gets a wall of 401s and has to work +out for themselves whether the stack is broken or the script is. + +The stack itself is fine, and there is a working equivalent: the **Admin Console → +End-to-end smoke test** card runs the same sequence from the browser, where the +session cookie already exists. `html/admin.html` describes it as mirroring +`smoketest.py`, which is now the only place that sequence actually runs. + +Rated Medium rather than Low because it is a verification tool that reports failure +on a healthy system — the failure mode most likely to be believed and acted on. + +### Why it is still open + +It was found while testing unrelated work (the User Directory) and is not a defect in +the product. Fixing it means choosing how the script gets credentials, which is a +small design decision about a deploy-time tool rather than a code fix, and it should +not ride along inside a feature branch. + +### What closing it takes + +Small — under an hour, stdlib only, matching the script's existing constraint. + +1. Add `--user` / `--password` arguments, defaulting to `WP_SMOKE_USER` / + `WP_SMOKE_PASSWORD` from the environment so the runbook does not put a password on + a command line. +2. Install an `http.cookiejar.CookieJar` on the opener in `call()`, then POST + `/api/auth/login` before the first check and assert it returned 200. There is a + working reference for both steps in the throwaway harness written for this branch + (`Client` in the scratch `http_check.py`), or in `html/admin.js`'s in-browser + version of the same flow. +3. Note in `DEPLOYMENT.md` that the account needs access to the project the script + creates — simplest is an admin account, since a `project_user` cannot create a + project. +4. Decide whether a missing credential is a hard failure or a skip with a clear + message. A silent 401 wall is what caused this entry. + +--- + +## 4. User Directory and nav drawer have not been run in a browser + +**Files:** `html/users.html`, `html/users.js`, `html/wp-sidenav.js`, +`html/wp-sidenav.css`, `html/console.css` +**Raised:** 2026-08-05, with the Project Super User work. + +### What is wrong + +This is a **gap in what has been verified, not a known defect.** The machine the code +was written on has no JavaScript engine available (no node, deno, or npx), so these +files have never been executed. What *has* been checked: + +- The server side they talk to: 93 scope/permission tests and 29 live HTTP tests + through the real dependency stack, all passing. +- Static analysis of the browser code: delimiter balance across all scripts (with a + tokenizer that handles nested template interpolation), every inline handler + resolving to a defined function, every `getElementById` target existing in its page, + and no leftover references to the functions that moved out of `admin.js`. + +What that cannot cover is anything only a browser decides: CSS layout, the drawer's +open/close transitions and focus trap, event wiring, and how the three role +renderings actually look with real data. + +### What it costs + +Unknown by definition, bounded by blast radius. A syntax or boot error in `users.js` +means a blank User Directory — obvious the moment anyone opens it, and it takes +nothing else down: `users.html` is a new page, and the drawer is additive to pages +that already worked without it. The server-side role and its scope rules are +independently tested and unaffected either way. + +The one thing to watch is `console.css`, which was extracted from `admin.html`'s +inline styles and is now shared. A rule lost in that move would show up as the Admin +Console losing its dense-table styling — the same symptom the deploy runbook already +tells you to look for ("one line per user", not three). + +### Why it is still open + +It closes with one manual page load, which needs a browser signed in to a real +deployment — not something to fake from a test harness. + +### What closing it takes + +Minutes. Hard-reload first (Ctrl+Shift+R) — the service worker caches the app shell +and `sw.js` bumped to `wp-suite-shell-v6`, so a normal reload can serve the old file +list and make a good deploy look broken. + +1. Open **users.html** as an admin: the table renders, rows are one line tall, and + the Permissions and Project role dropdowns are populated. +2. Open it as a **Project Super User**: the blue scope banner names their project(s), + the create form demands at least one project, and any account also on a job they + don't administer shows as `read-only` with a reason on hover. +3. Open it as a **project user**: six columns, no controls, no create form. +4. Open **field.html** on a phone or a narrow window: the ☰ opens the drawer, Escape + and the scrim close it, and Admin Console appears only for admins. +5. Open **admin.html** and confirm the tables still look dense and correct — that is + the `console.css` extraction check. + +Delete this entry once those five are done.