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
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:
co-authored by
Claude Opus 5.5
parent
8571e6854c
commit
cd0287537e
@@ -404,9 +404,36 @@ no runtime assertion can make: that the identity feature names no SMTP detail, t
|
||||
schema gained a token column and no identity code hashes or compares a token, that nothing
|
||||
interpolates a token, link, address, or body into a log line, that a device has no email, password,
|
||||
or verification concept, that no browser source imports Better Auth or Core's mail, and that the
|
||||
shell's only use of browser storage is the sidebar's expanded/collapsed mode — `localStorage` named
|
||||
only by the entry point, one write of one fixed key, and no storage API in any file that holds the
|
||||
reset token ([ADR 0058](../architecture/decisions/0058-dashboard-shell-navigation-and-lucide-icons.md)).
|
||||
shell's uses of browser storage are exactly two: the sidebar's expanded/collapsed mode
|
||||
([ADR 0058](../architecture/decisions/0058-dashboard-shell-navigation-and-lucide-icons.md)) and the
|
||||
pre-paint appearance cache
|
||||
([ADR 0062](../architecture/decisions/0062-account-area-and-synced-appearance-preferences.md)).
|
||||
`localStorage` is named once by the entry point and once, read-only, by the pre-paint script. There is
|
||||
one write of each fixed key, one removal of the appearance key, and no storage API in any file that
|
||||
holds the reset token.
|
||||
|
||||
The account area
|
||||
([ADR 0062](../architecture/decisions/0062-account-area-and-synced-appearance-preferences.md)) is
|
||||
proven at each layer:
|
||||
|
||||
- `core/tests/account-preferences.test.ts` covers the closed preference model, its strict parser, the
|
||||
table's typed columns, and that the migration's `CHECK` lists equal the model.
|
||||
- `core/tests/account-store.integration.ts` uses real PostgreSQL. It proves defaults without writing a
|
||||
row, saving each value, partial updates, isolation between two people, persistence across a new
|
||||
connection, the database refusing an out-of-model value, and the cascade on delete.
|
||||
- `apps/api/tests/account-routes.test.ts` covers the routes. Anonymous and device callers are refused,
|
||||
only the session's account is ever read or written whatever the request names, there is no route
|
||||
that addresses another person, and validation, `Origin`, body limit, failures, and CORS preflight
|
||||
all behave as specified. It also holds Core's value sets equal to the design tokens'.
|
||||
- `apps/api/tests/api-http.integration.ts` runs two real accounts over real HTTP sessions, with the
|
||||
same isolation proven end to end.
|
||||
- `surfaces/shell/tests/appearance-preference.test.ts` covers the cache, the pre-paint script (run in
|
||||
the DOM), and the one handle over the ADR 0060 controller.
|
||||
- `surfaces/shell/tests/account-appearance.test.tsx` covers the account control's identity, both
|
||||
pages, live switching, saving, reverting on failure, reconciling with the account, cross-tab
|
||||
following, sign-out forgetting, and the phone drawer.
|
||||
- The deploy smoke's real Chromium checks Light and Dark rendering, reload persistence, an emulated OS
|
||||
change, reduced motion, a module's Shadow DOM following the theme, and phone width.
|
||||
|
||||
Unit suites (`core/tests/module-storage.test.ts`, `core/tests/module-storage-lifecycle.test.ts`) use an
|
||||
injected in-memory provider and never touch the network. They prove the parts the protocol cannot:
|
||||
|
||||
Reference in New Issue
Block a user