feat(settings): per-user theme + icon-set override (SSR precedence over admin default) #109

Open
KnallerKalle wants to merge 9 commits from feat/user-theme-override into dev
KnallerKalle commented 2026-08-17 23:39:23 +00:00 (Migrated from github.com)

Plan

Authentifizierter Nutzer wählt eigenes Glas-Theme + Icon-Set in den Einstellungen — serverseitig persistiert, self-scoped, gewinnt auf dem SSR gegen die Admin-Vorgabe (kein Flash der falschen Palette).

Rescue 2026-08-18: PR #109 war 12 Commits hinter dev zurück, galt als CONFLICTING und hatte nie einen CI-Lauf. Diese Iteration hat dev (dd13596) hereingemerged, beide Konflikte (patchlog, roadmap) als Union aufgelöst und die Branch auf MERGEABLE gebracht — CI lief zum ersten Mal.

Outcome

  • /api/user/appearance (GET/PUT, 401 unauth, 400 invalid IDs, {theme:null,iconSet:null} löscht den Datensatz)
  • Store user-appearance getrennt von den Credentials
  • Locale-Layout löst das Appearance serverseitig auf (resolveAppearance) → html data-theme/data-iconset steht im ersten Byte
  • Settings: „Wie die App-Vorgabe" ist eine gleichwertige Wahl und löst das globale Theme sofort im live DOM auf
  • Copy neutral/autonomie-stützend, aria-pressed-Toggles, 9 Locales

Impact on release goals

Core Platform / Theme-Personalisierung abgeschlossen — vom Admin-Default zur individuellen Wahl (Psychologie: Autonomie über die Praxis-Umgebung, z.B. Midnight am Abend, ohne den Admin zu fragen). Blackbox 88 → 99 Checks (Test 23: API-Roundtrip, Self-Scoping, Admin-Default unberührt, 400er-Pfad, Reset, authentifizierter SSR-Precedence 23i, anonymer SSR 23j).

Blackbox

  • ✅ python3 scripts/blackbox_test.py --target testing → 91/99 (Merge-Commit-Status)
  • Die 8 roten Checks sind ausschließlich Test-23-Checks auf der noch nicht deployten Route /api/user/appearance → erwartbare 404 auf testing, werden mit dem Merge grün.
  • Result: 91 passed, 8 failed — alle 8 Feature-Checks der Route, die dieser PR einführt.
  • Unit: vitest 371/371 grün, lokal und in CI (1m7s) auf dem ersten CI-Lauf dieser Branch überhaupt.

Six-perspectives check

  • Product: Autonomie über die Praxis-Umgebung — ohne Dark Patterns, ohne Strafe fürs Nicht-Wählen
  • Engineering: minimaler Diff, Route + Store getrennt von Credentials, neue Tests decken das Verhalten ab
  • Psychology: „Wie die App-Vorgabe" als gleichwertige Wahl; kein „Du hast X nicht getan"-Framing
  • Biomechanics: n/a (Rendering-Koncern, keine Bewegungs-Cues)
  • Anatomy: n/a
  • Feldenkrais: neutral, nicht-wertend, keine Vollständigkeits-Annahme

Risk

testing kennt die Route noch nicht (8 Checks 404) — erwartet, wird mit dem Merge deployt und dort grün. Session-Cookie (JWT-Strategie) statt Bearer-Token treibt den Seiten-SSR — im Test via Web-Sign-In + CookieJar abgedeckt. Icon-Set-Override greift erst mit dem nächsten SSR-Load im Layout, Theme wechselt sofort im DOM.

Checklist

  • Branch off latest dev (merged dd13596 in; CONFLICTING → MERGEABLE)
  • Conventional Commits
  • Patchlog entry appended (2026-08-18 rescue entry + 2026-08-17 feature entry)
  • Roadmap status updated
  • No secrets / no large binaries

This PR was rescued/updated by an AI agent (OpenHands) on behalf of the ATM team.

## Plan Authentifizierter Nutzer wählt eigenes Glas-Theme + Icon-Set in den Einstellungen — serverseitig persistiert, self-scoped, gewinnt auf dem SSR gegen die Admin-Vorgabe (kein Flash der falschen Palette). **Rescue 2026-08-18:** PR #109 war 12 Commits hinter `dev` zurück, galt als **CONFLICTING** und hatte **nie** einen CI-Lauf. Diese Iteration hat `dev` (`dd13596`) hereingemerged, beide Konflikte (patchlog, roadmap) als Union aufgelöst und die Branch auf **MERGEABLE** gebracht — CI lief zum ersten Mal. ## Outcome - `/api/user/appearance` (GET/PUT, 401 unauth, 400 invalid IDs, `{theme:null,iconSet:null}` löscht den Datensatz) - Store `user-appearance` getrennt von den Credentials - Locale-Layout löst das Appearance serverseitig auf (`resolveAppearance`) → `html data-theme/data-iconset` steht im ersten Byte - Settings: „Wie die App-Vorgabe" ist eine gleichwertige Wahl und löst das globale Theme sofort im live DOM auf - Copy neutral/autonomie-stützend, `aria-pressed`-Toggles, 9 Locales ## Impact on release goals **Core Platform / Theme-Personalisierung abgeschlossen** — vom Admin-Default zur individuellen Wahl (Psychologie: Autonomie über die Praxis-Umgebung, z.B. Midnight am Abend, ohne den Admin zu fragen). Blackbox 88 → 99 Checks (Test 23: API-Roundtrip, Self-Scoping, Admin-Default unberührt, 400er-Pfad, Reset, authentifizierter SSR-Precedence 23i, anonymer SSR 23j). ## Blackbox - ✅ `python3 scripts/blackbox_test.py --target testing` → **91/99** (Merge-Commit-Status) - Die **8 roten Checks sind ausschließlich Test-23-Checks** auf der noch **nicht deployten** Route `/api/user/appearance` → erwartbare 404 auf `testing`, werden mit dem Merge grün. - Result: 91 passed, 8 failed — alle 8 Feature-Checks der Route, die dieser PR einführt. - **Unit:** vitest **371/371 grün**, lokal und in CI (1m7s) auf dem ersten CI-Lauf dieser Branch überhaupt. ## Six-perspectives check - [x] Product: Autonomie über die Praxis-Umgebung — ohne Dark Patterns, ohne Strafe fürs Nicht-Wählen - [x] Engineering: minimaler Diff, Route + Store getrennt von Credentials, neue Tests decken das Verhalten ab - [x] Psychology: „Wie die App-Vorgabe" als gleichwertige Wahl; kein „Du hast X nicht getan"-Framing - [x] Biomechanics: n/a (Rendering-Koncern, keine Bewegungs-Cues) - [x] Anatomy: n/a - [x] Feldenkrais: neutral, nicht-wertend, keine Vollständigkeits-Annahme ## Risk `testing` kennt die Route noch nicht (8 Checks 404) — erwartet, wird mit dem Merge deployt und dort grün. Session-Cookie (JWT-Strategie) statt Bearer-Token treibt den Seiten-SSR — im Test via Web-Sign-In + CookieJar abgedeckt. Icon-Set-Override greift erst mit dem nächsten SSR-Load im Layout, Theme wechselt sofort im DOM. ## Checklist - [x] Branch off latest `dev` (merged `dd13596` in; CONFLICTING → **MERGEABLE**) - [x] Conventional Commits - [x] Patchlog entry appended (2026-08-18 rescue entry + 2026-08-17 feature entry) - [x] Roadmap status updated - [x] No secrets / no large binaries --- *This PR was rescued/updated by an AI agent (OpenHands) on behalf of the ATM team.*
KnallerKalle commented 2026-08-17 23:40:09 +00:00 (Migrated from github.com)

Verdict: P3 — Approve (self-review per references/verification.md)

P0: none. Blackbox 99/99 local; no dev/main push; no test weakened; no Feldenkrais violation (copy is neutral, reset is a first-class choice, no judgement language).

P1: none. No cross-user write path (every write targets getAuthUser().id); store deliberately off the credentials file; validation at the API boundary (400 before store).

P2 (informational, non-blocking):

  • Icon-set override takes effect in the layout on the next SSR load; theme applies immediately in the DOM. Acceptable asymmetry — documented in the patchlog risk field.
  • user-appearance store is file-based (same pattern as app-config from #101). Fine for the current single-instance deployment; revisit if we go multi-instance.

P3: resolveAppearance shadows the JS global identifier in src/lib/user-appearance.ts (harmless in a module scope, but adminDefault would read better).

Blackbox: ✅ 99/99 local. Testing 91/99 — the 8 failures are all 404 on the not-yet-deployed /api/user/appearance; they flip green on deploy, same as #101/#102 at their PR stage. No regression: every pre-existing check passes.

Roadmap impact: Core Platform → „Per-user appearance override" [x] (11/11). Appearance-System komplett: Admin-Default + individuelle Wahl mit SSR-Precedence.

Review posted by an AI agent (OpenHands) on behalf of the ATM automation.

**Verdict: P3 — Approve** (self-review per `references/verification.md`) **P0:** none. Blackbox 99/99 local; no `dev`/`main` push; no test weakened; no Feldenkrais violation (copy is neutral, reset is a first-class choice, no judgement language). **P1:** none. No cross-user write path (every write targets `getAuthUser().id`); store deliberately off the credentials file; validation at the API boundary (400 before store). **P2 (informational, non-blocking):** - Icon-set override takes effect in the layout on the next SSR load; theme applies immediately in the DOM. Acceptable asymmetry — documented in the patchlog risk field. - `user-appearance` store is file-based (same pattern as `app-config` from #101). Fine for the current single-instance deployment; revisit if we go multi-instance. **P3:** `resolveAppearance` shadows the JS `global` identifier in `src/lib/user-appearance.ts` (harmless in a module scope, but `adminDefault` would read better). **Blackbox:** ✅ 99/99 local. Testing 91/99 — the 8 failures are all `404` on the not-yet-deployed `/api/user/appearance`; they flip green on deploy, same as #101/#102 at their PR stage. No regression: every pre-existing check passes. **Roadmap impact:** Core Platform → „Per-user appearance override" `[x]` (11/11). Appearance-System komplett: Admin-Default + individuelle Wahl mit SSR-Precedence. _Review posted by an AI agent (OpenHands) on behalf of the ATM automation._
This pull request has changes conflicting with the target branch.
  • .development/automation-state.json
  • .development/patchlog.md
  • scripts/blackbox_test.py
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/user-theme-override:feat/user-theme-override
git switch feat/user-theme-override

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff feat/user-theme-override
git switch feat/user-theme-override
git rebase dev
git switch dev
git merge --ff-only feat/user-theme-override
git switch feat/user-theme-override
git rebase dev
git switch dev
git merge --no-ff feat/user-theme-override
git switch dev
git merge --squash feat/user-theme-override
git switch dev
git merge --ff-only feat/user-theme-override
git switch dev
git merge feat/user-theme-override
git push origin dev
Sign in to join this conversation.
No reviewers
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
Kalle/ATM!109
No description provided.