# Smoke Cleanup Delta — 2026-04-26 (post t-paliad-038/039/040)

Original report: `tests/smoke-auth-2026-04-25.md` (10 bugs).
This is a delta report — only changes since the original. No URL grid replay.

Tester: `tester@hlc.de` (admin), Playwright headless against `https://paliad.de`.

## What shipped

| Task | Branch | Merge | What |
|---|---|---|---|
| t-paliad-038 | `mai/brunel/projects-detail-rename` | d81da4b | `/projects/{id}` notfound + German DOM/URL leftovers in `projects-detail` |
| t-paliad-039 | `mai/brunel/urgent-deadlines-id` | f782ef7 | `/deadlines/{id}` notfound, `/deadlines` "Invalid Date", `/appointments/{id}` notfound |
| (no task #) | `mai/brunel/footer-tool-by-flexsiebels` | 3ff982c | Footer "Nur für internen Gebrauch" → "ein Werkzeug von flexsiebels.de" |
| (no task #) | `mai/brunel/project-tabs-nil-empty` | b4a409a | `/projects/{id}` tabs blank — list services returned JSON `null` → client `.length` crash |
| t-paliad-040 | `mai/brunel/smoke-cleanup-batch-2` | 3a1eb07 | `/whatsnew` alias + `/settings/{tab}` deep-link redirects |

## Bug status

### Fixed

- **Bug 1** (`/projects/{id}` SSR notfound while API 200) — t-paliad-038. `parseAkteID` was checking the German URL prefix; renamed to `parseProjectID` reading `/projects/{id}`. Confirmed via Playwright: project chrome + tabs render.
- **Bug 7** (`/whatsnew` bare 404) — t-paliad-040. 301 → `/changelog` via `internal/handlers/redirects.go`. Confirmed: `curl -sI /whatsnew` → 301 Location: /changelog.
- **Bug 8** (`/settings` tab deep-link 404) — t-paliad-040. Replaced single CalDAV-only handler with generic `/settings/{tab}` redirector. Map accepts both German tab IDs (`profil`, `benachrichtigungen`, `dezernat`) and English aliases (`profile`, `notifications`, `department`); unknown slugs fall back to `/settings` (default tab) instead of 404. Confirmed in Playwright as logged-in admin: `/settings/notifications` → `/settings?tab=benachrichtigungen` and the "Benachrichtigungen" tab is active. Same for `/settings/dezernat`, `/settings/profile`, `/settings/department`.
- **Bug 9** (404 has no chrome) — already shipped in t-paliad-037. Verified still in place: `/garbage` returns 404 with sidebar + footer + "Zurück zum Dashboard" CTA.
- **`/deadlines/{id}` notfound** (caught after smoke ran) — t-paliad-039. `parseFristID` checked `/fristen` URL prefix; renamed to `parseDeadlineID` reading `/deadlines`. Same class as Bug 1.
- **`/deadlines` "Invalid Date"** (caught after smoke ran) — t-paliad-039. `fmtDate` blindly appended `T00:00:00` to API dates; API now returns full ISO datetime. Guarded with `iso.length === 10` / `iso.slice(0, 10)`.
- **`/projects/{id}` tabs blank** (m reported after t-paliad-038) — empty list services returned JSON `null` (sqlx scan into `var rows []T` leaves nil slice; `encoding/json` marshals nil slice as `null`). Fixed at the source for 9 services (`party`, `project`, `deadline`, `appointment`, `note`, `checklist_instance`, `team`, `department` + their `WithProject` variants); client also coerces with `?? []`.

### Skipped (documented)

- **Bug 10** (login form 401 console replay) — **not fixable from JS**. Reproduced cleanly: a failed `/api/login` with the wrong password emits the exact one-line console error `[ERROR] Failed to load resource: the server responded with a status of 401`. That message is generated by the browser's network stack itself, not by `login.ts` (which has no `console.error` call — it shows the error in the form via `showError`). The only "fixes" available either compromise the security pattern (return HTTP 200 with `{ok: false}` body so 4xx never appears) or don't actually suppress the browser log (4xx → 4xx, status code change doesn't help). Brief explicitly authorised the skip ("If this turns out to be a non-trivial yak-shave, skip it"). Severity is low; the form UX itself works correctly.

### Still open from original report

- **Bug 2** — same root cause as Bug 1 / Bug `/deadlines/{id}` / Bug `/appointments/{id}` (German URL prefix in `parse*ID`). All three now fixed in t-paliad-038 + t-paliad-039.
- **Bug 3** — `/projects` 500 (RLS function bodies) — already fixed in t-paliad-036 (migration 021).
- **Bugs 4 / 5 / 6** — i18n leaks, `/api/departments` 500, dashboard activity — already fixed in t-paliad-037.
- **Bugs not numbered above** (none) — original report had Bugs 1–10; all addressed.

## What's still off (post-fix smoke)

- **None blocking.** One known cosmetic: the browser's auto-emitted "Failed to load resource: 401" on a wrong-password login attempt (Bug 10) is unavoidable without changing the auth response shape. Documented above.
- **Console clean** on the canonical pages I exercised: `/dashboard`, `/projects`, `/projects/{id}` (history/parties/deadlines/appointments/team), `/deadlines`, `/deadlines/{id}`, `/appointments`, `/appointments/{id}`, `/settings`, `/settings/notifications`, `/settings/dezernat`, `/changelog`, `/whatsnew`. No JS errors.
- **Footer copy** — confirmed live: "© 2026 Paliad — ein Werkzeug von flexsiebels.de" on `/dashboard` and the marketing index.

## Verdict

**Clean.** All actionable items from the original 2026-04-25 smoke report are fixed (8/10) or explicitly deferred with rationale (Bug 10). No new regressions surfaced during verification. Ready for the next smoke pass.

## Out of scope (deferred — m to decide)

- **`Hogan Lovells` → dynamic `FIRM_NAME` constant** — m requested it, head asked to hold for architectural sign-off. WIP draft exists in `git stash` on this worker; can be revived as its own task.
