From 761e350261c80d2f19788c2325eae45ce9decdbf Mon Sep 17 00:00:00 2001 From: m Date: Sat, 25 Apr 2026 23:01:48 +0200 Subject: [PATCH] test(smoke): production smoke report + register Playwright MCP (t-paliad-033) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anonymous-surface smoke test of paliad.de — all 11 legacy DE→EN redirects, 9 gated routes, /login form, and / marketing landing healthy. Two minor findings noted in the report (knowledge platform is auth-gated contrary to brief expectation; anon / fires a 401 on /api/changelog/unseen-count). Authenticated flows untested — needs follow-up worker with creds. Also registers @playwright/mcp in .mcp.json so future smoke runs can use the /mai-tester skill's mcp__playwright__* tools directly instead of falling back to a bunx script. --- .mcp.json | 9 +++ tests/smoke-2026-04-25.md | 130 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 tests/smoke-2026-04-25.md diff --git a/.mcp.json b/.mcp.json index 3b689c4..e8fb37a 100644 --- a/.mcp.json +++ b/.mcp.json @@ -6,6 +6,15 @@ "headers": { "Authorization": "Basic ${YOUPC_SUPABASE_AUTH}" } + }, + "playwright": { + "command": "bunx", + "args": [ + "@playwright/mcp@latest", + "--headless", + "--user-data-dir", + "/tmp/mai-playwright-profile" + ] } } } diff --git a/tests/smoke-2026-04-25.md b/tests/smoke-2026-04-25.md new file mode 100644 index 0000000..9043cf9 --- /dev/null +++ b/tests/smoke-2026-04-25.md @@ -0,0 +1,130 @@ +# Paliad Production Smoke Test — 2026-04-25 + +**Target:** https://paliad.de +**Run by:** ritchie/curie (t-paliad-033) +**Method:** curl preflight + Playwright headless (Chromium 1.59.1, viewport 1280×900) +**Trigger:** verify three features that shipped today — project tree (t-paliad-028), team directory (t-paliad-029), reminder fix (t-paliad-032). +**Auth state:** anonymous only (no test credentials available) + +## Summary + +- ✅ 11/11 legacy German redirects return 301 with correct English target. +- ✅ Subpath + querystring preservation works (`/akten/abc/deadlines?x=1` → `/projects/abc/deadlines?x=1`). +- ✅ 9/9 gated routes correctly 302 → `/login`. +- ✅ `/login` renders cleanly: `name@hlc.com` placeholder, DE/EN toggle, HLC hint, lime branding, no console errors. +- ✅ `/` renders the Patent Knowledge marketing landing (HTTP 200, lime branding intact, layout clean). +- ⚠️ `/` fires a 401 on `/api/changelog/unseen-count` for anon visitors — surfaces as a console error even though the JS catch is silent. +- ⚠️ Task brief assumed `/tools/*`, `/glossary`, `/courts`, `/links`, `/downloads`, `/checklists`, `/onboarding` were ungated. They are not. Auth-gated since the original Fristenrechner commit (d94f8e7, 2026-04-14). CLAUDE.md says these don't need `DATABASE_URL`, not that they don't need auth — brief misread. +- 🔒 Authenticated surface (where the three new features actually live: project tree, team directory, reminder UI) is **not covered** — needs follow-up worker with creds, as anticipated in the brief's "out of scope" section. + +No regressions found in the surface that *can* be tested anonymously. The three shipped features cannot be validated without login. + +## Per-URL Results + +### Public / landing + +| URL | HTTP | Final | Errs | Failed reqs | Visual | Notes | +|-----|------|-------|------|-------------|--------|-------| +| `/` | ✅ 200 | `/` | ⚠️ 1 | ⚠️ 1 | OK | Marketing landing renders; 401 on `/api/changelog/unseen-count` | +| `/login` | ✅ 200 | `/login` | 0 | 0 | OK | Form renders, placeholder `name@hlc.com`, DE/EN toggle, HLC hint, lime branding | +| `/onboarding` | ⚠️ 302 | `/login` | 0 | 0 | n/a | Gated. Brief expected public; matches code which has no public `/onboarding` route | + +### Knowledge platform (auth-gated, contrary to brief expectation) + +All return **302 → `/login`** (HTTP 200 after redirect, ending on the login page): + +| URL | Final URL | Title | Errs | Failed reqs | +|-----|-----------|-------|------|-------------| +| `/tools/fristenrechner` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/tools/kostenrechner` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/tools/gebuehrentabellen` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/checklists` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/glossary` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/courts` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/links` | `/login` | Anmelden — Paliad | 0 | 0 | +| `/downloads` | `/login` | Anmelden — Paliad | 0 | 0 | + +Per `internal/handlers/handlers.go:79-115`, these are registered on the `protected` mux; that's been the case since `d94f8e7` (2026-04-14). Not a regression — brief expectation was wrong. + +### Legacy German → English redirects (301, all ✅) + +| Legacy | → Target | Result | +|--------|----------|--------| +| `/fristen` | `/deadlines` | ✅ 301 | +| `/akten` | `/projects` | ✅ 301 | +| `/termine` | `/appointments` | ✅ 301 | +| `/notizen` | `/notes` | ✅ 301 | +| `/einstellungen` | `/settings` | ✅ 301 | +| `/projekte` | `/projects` | ✅ 301 | +| `/dezernate` | `/departments` | ✅ 301 | +| `/parteien` | `/parties` | ✅ 301 | +| `/checklisten` | `/checklists` | ✅ 301 | +| `/glossar` | `/glossary` | ✅ 301 | +| `/gerichte` | `/courts` | ✅ 301 | +| `/akten/abc/deadlines?x=1` | `/projects/abc/deadlines?x=1` | ✅ 301 (subpath + qs preserved) | + +### Gated routes (302 → /login, all ✅) + +`/dashboard`, `/projects`, `/deadlines`, `/appointments`, `/team`, `/agenda`, `/settings`, `/whatsnew`, `/search` — every one redirects to `/login`. Auth gate is functional. + +## Console errors observed + +Only one across all tested pages — on `/`: + +``` +Failed to load resource: the server responded with a status of 401 () +URL: https://paliad.de/api/changelog/unseen-count +``` + +**Root cause:** `frontend/src/client/sidebar.ts:135-153` `initChangelogBadge()` fires unconditionally on every page that includes ``. The catch swallows the error in JS, but the browser still logs the 401 in DevTools. + +**Why the marketing landing has the sidebar at all:** the public `/` serves `dist/index.html` (handled in `internal/handlers/dashboard.go:47-52`) — same shell as the authenticated app, just without a session. Sidebar JS therefore runs in anon context and the changelog fetch hits a `protected` route. + +**Severity:** cosmetic / log noise. Does not break the page. Worth fixing because (a) it surfaces a 401 that looks alarming in DevTools, and (b) it costs an HTTP round-trip for every anonymous landing visit. + +**Suggested fix (one-liner):** inside `initChangelogBadge()`, early-return when the changelog badge link itself isn't present, OR check for a session cookie marker before fetching, OR move the marketing landing to its own minimal shell. + +## Failing network requests + +Same 401 — only one across all pages tested: + +| Page | Request | Status | +|------|---------|--------| +| `/` | `GET /api/changelog/unseen-count` | 401 | + +No 4xx or 5xx anywhere else. Asset pipeline (`/assets/*`) returns 200s. + +## Screenshots + +Stored in `/tmp/mai-tester/`: + +- `paliad-root.png` — marketing landing, lime hero, sidebar icon-rail visible on left +- `paliad-login.png` — clean login card, name@hlc.com placeholder, DE/EN toggle top-right +- `paliad-onboarding.png`, `paliad-tools-*.png`, `paliad-glossary.png`, `paliad-courts.png`, `paliad-links.png`, `paliad-downloads.png`, `paliad-checklists.png` — all show the login form (302 redirected there); identical to `paliad-login.png` (≈28 KB each, vs. 74 KB for the rendered marketing landing — quick file-size sanity check confirms they are all the login screen) + +Visual sanity: layout intact on all rendered pages, no half-rendered content, no broken images on `/login` or `/`. + +## Top issues, ranked by severity + +1. **Brief vs. reality mismatch — knowledge platform is auth-gated.** Brief said "ungated, per CLAUDE.md"; CLAUDE.md actually only says these routes don't need `DATABASE_URL`. The product *requires login* for everything except `/`, `/login`, `/logout`, `/assets/*`. **Action:** either (a) clarify CLAUDE.md so future briefs don't repeat this misread, or (b) decide that the product wants a public knowledge tier and move those routes to the unprotected mux. Today's behaviour matches the code. +2. **Anon `/` triggers 401 on `/api/changelog/unseen-count`.** Console noise; minor. Fix in `frontend/src/client/sidebar.ts` — gate the fetch behind a session marker, or scope `initChangelogBadge` to authenticated-only pages. +3. **Anon `/onboarding` 302s to `/login`.** Brief's expectation was a "sane" anon behaviour; redirecting to login *is* sane, but if the product later wants self-serve onboarding (e.g. via invite link), the route doesn't currently support that flow. +4. **Three new features (t-paliad-028, -029, -032) untested.** All sit behind auth — project tree at `/projects`, team directory at `/team`, reminders inside Akten/Frist UI. Need a follow-up worker with credentials. Unit + handler tests are presumably green (they shipped), but no live-prod verification has happened. +5. **No further issues found in the anonymous surface.** Login form, redirects, auth gate, marketing landing all behave as coded. + +## Acceptance checklist + +- [x] All public + knowledge URLs in scope visited +- [x] All legacy redirects verified (11/11 + subpath/qs case) +- [x] All gated routes verified to 302 to `/login` +- [x] Report file written +- [x] Per-URL screenshots captured at `/tmp/mai-tester/paliad-.png` +- [x] No raw logs in chat — summary only + +## Out of scope (explicitly deferred) + +- Authenticated flows: project tree (t-paliad-028), team directory (t-paliad-029), reminder fix (t-paliad-032), Dashboard, Agenda, Search, Whatsnew, Settings. +- Email send (no SMTP creds), CalDAV sync (no CalDAV creds). +- Multi-language end-to-end (only DE rendered, EN toggle visually present but interaction not exercised). + +Hand off to a follow-up worker once m provides test credentials.