Add the account area and account-synced Appearance preferences
CI / verify (pull_request) Successful in 1m10s
CI / infrastructure-smoke (pull_request) Successful in 34s
CI / package-release (pull_request) Successful in 50s
CI / migration-smoke (pull_request) Successful in 2m26s
CI / image-build (pull_request) Successful in 1m12s
CI / deploy-smoke (same-origin) (pull_request) Successful in 42s
CI / package-publication (pull_request) Successful in 54s
CI / deploy-smoke (split) (pull_request) Successful in 3m17s

Stage 1 PR 6 (ADR 0062). /account shows who is signed in; /account/appearance
chooses System, Light, or Dark and reduced motion (System, Reduce, Allow).

- Core: ekklesia_core_user_preference, one typed, CHECK-constrained,
  nullable column per preference (null = never chosen), migration
  0008_user_preferences (additive), @ekklesia/core/account store, and the
  authenticated-baseline permission core.account.self.manage.
- API: GET /api/v1/account (name, email, preferences) and partial
  PATCH /api/v1/account/preferences, self-only by construction: no user id
  is accepted anywhere; trusted Origin and body limit on the mutation.
- Shell: the account control shows name, email, and initials (never the
  unvetted image URL) and offers Account, Appearance, Sign out; native
  radio groups apply a choice at once through the ADR 0060 controller and
  save it; the server's answer wins and a failed save reverts.
- First paint: a classic, same-origin, render-blocking appearance.js in
  <head> applies a two-word localStorage cache before paint (no inline
  script, CSP unchanged). The account replaces the cache on every load,
  sign-out clears it, and other tabs follow via the storage event.
- Deploy smoke: real-Chromium checks for light/dark, OS emulation,
  overrides, reload persistence, pre-paint, Shadow DOM modules, reduced
  motion, the display staying light, and phone width; the browser
  container gets a 512 MiB /dev/shm so a long session no longer fails
  requests with ERR_INSUFFICIENT_RESOURCES.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-10-14 23:56:50 -05:00
co-authored by Claude Opus 5.5
parent 8571e6854c
commit cd0287537e
88 changed files with 6404 additions and 158 deletions
+13 -4
View File
@@ -941,8 +941,7 @@ The Dashboard follows the operating system's **Light or Dark** appearance and **
setting, live and without a reload, and so does every module's UI, through the same design tokens
([ADR 0060](docs/architecture/decisions/0060-light-dark-system-theme-and-motion.md)). The dark theme is
designed rather than inverted, every text and focus pairing is contrast-tested to WCAG AA in both
schemes, corners scale from one `radius.scale` token, and an explicit Light or Dark choice is one call
away once account preferences exist. Displays stay light.
schemes, and corners scale from one `radius.scale` token. Displays stay light.
**Settings** has its own place in the sidebar
([ADR 0061](docs/architecture/decisions/0061-settings-hierarchy-and-module-settings-routes.md)): a
@@ -952,6 +951,14 @@ and updated (`/settings/discover/browse`, `/installed`, `/updates`); configuring
Settings page. A person sees only what the server says they may administer, and no Settings link at all
when that is nothing. The pages are placeholders until each section is built.
**Your account** is at the bottom of the sidebar, showing your name, email, and initials
([ADR 0062](docs/architecture/decisions/0062-account-area-and-synced-appearance-preferences.md)).
`/account` shows who you are signed in as. On `/account/appearance` you choose **System, Light, or
Dark** and **reduced motion** (System, Reduce, or Allow). A choice takes effect at once, is saved to
your account so it follows you to every device, and is applied before the first paint on your next
visit. Managing your own appearance needs no administrative permission. Profile editing and an
avatar image are not part of this.
## Quick start
Prerequisites: Node.js 24 LTS, pnpm 11.12, and Docker with Compose.
@@ -1007,7 +1014,7 @@ Modules
✓ Dependency graph valid
Dependency order is empty.
✓ Permission registry composed
6 permissions registered
7 permissions registered
○ Module lifecycle skipped
DATABASE_URL is not configured.
○ Module configuration skipped
@@ -1017,7 +1024,7 @@ Data definitions
✓ Schemas validated
0 modules · 0 tables
✓ Migrations validated
7 migrations · checksums valid
9 migrations · checksums valid
core:0000_identity_core_tables · f8f2086ef06f
core:0001_authorization_core_tables · 830e1fbc26d0
core:0002_authorization_integrity · 634294731180
@@ -1025,6 +1032,8 @@ Data definitions
core:0004_module_lifecycle_state · c8b5d8b3d48b
core:0005_module_configuration · c8d57f24f84b
core:0006_device_identity · 1db97b7e3ac5
core:0007_verified_bootstrap_owners · 49013062f3e0
core:0008_user_preferences · fa9d4b0bb9d3
PostgreSQL
✓ Database TLS verified