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]>
39 lines
2.1 KiB
HTML
39 lines
2.1 KiB
HTML
<!doctype html>
|
|
<html lang="en" style="min-width: 0; scrollbar-gutter: stable">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
<!-- The API's origin (ADR 0045). The API serving this page fills it in at startup; empty means
|
|
this page's own origin, the same-origin topology. Never an inline script, so a strict
|
|
script-src needs no exception for it. -->
|
|
<meta content="" name="ekklesia-api-origin" />
|
|
<!-- Light and dark are both supported (ADR 0060). The browser paints its own canvas in the
|
|
system's scheme before any script runs, so a dark system never flashes white first. -->
|
|
<meta content="light dark" name="color-scheme" />
|
|
<!-- The pre-paint appearance script (ADR 0062): classic, same-origin, and render-blocking on
|
|
purpose, so a person who chose Light or Dark sees it from the first frame. It reads this
|
|
browser's cached copy of their choice (two words, nothing about the account) and sets the
|
|
theme attributes and the colour scheme above. Never inline. -->
|
|
<script src="/assets/ekklesia-dashboard/appearance.js"></script>
|
|
<title>Ekklesia</title>
|
|
</head>
|
|
<body
|
|
style="
|
|
margin: 0;
|
|
min-width: 0;
|
|
background: var(--ekklesia-background-page);
|
|
color: var(--ekklesia-text-primary);
|
|
"
|
|
>
|
|
<!-- The shell's root. A module UI never receives this element: it is given a container the
|
|
shell creates inside its own layout. -->
|
|
<div id="ekklesia-host"></div>
|
|
<!-- A real module script, from the same origin, with no inline script anywhere on the page:
|
|
a deployment can therefore apply a strict script-src without exceptions, and the runtime
|
|
`import()` of a published module artifact stays same-origin under it. The path is absolute
|
|
and fixed, exactly like the display host's, so it names one host-owned route rather than a
|
|
file relative to whatever URL served the page. -->
|
|
<script src="/assets/ekklesia-dashboard/app.js" type="module"></script>
|
|
</body>
|
|
</html>
|