SETTINGS: one reusable card/row block for every section + see-through Settings and toasts #402

Closed
opened 2026-09-29 05:23:48 +00:00 by kayg · 17 comments
Owner

Requests (owner, 2026-09-29)

  1. "please make a single reusable card block for settings with extensible properties so it can be reused and one issue can be fixed easily!"
  2. "the thing about settings being transparent along with more transparent toasts?" — the Settings overlay and toasts still look nearly opaque (screenshot: an almost white 'Link to "Text" copied' toast; Settings panel). #289/#354 asked for one overlay transparency, much more transparent, inner cards slightly more opaque; toasts use the same glass.
  3. A toast detail the owner described a day ago ("the toast border line description") is not in any issue — waiting for the owner to restate it; add it here when they do.

Build

  • One Settings card block in packages/ui (or apps/web settings/parts, whichever is the shared layer): SettingsCard with extensible props/snippets (title + LinkedHeading deep link, description, rows, footer actions, empty state, variants such as danger), and one SettingsRow (icon, title, chips, meta with tone, trailing actions, ⋯ menu, extra/full-width slot, stacking rules for narrow widths, icon centred on the text block). Migrate every Settings section to it (Account, Apps, Appearance, Editor, Notifications, Calendars, Mail, AI, Photos, Plugins, Maintenance, all Admin pages) and delete the per-section copies (SettingsGroup, AccountRow and ad-hoc rows fold into it). A guard test fails if a Settings section renders a card or row outside the shared block.
  • Shadows: keep the new --glass-shadow-reach rule (d0d83a32) inside the block's scroll parents.
  • Transparency: the Settings overlay surface and toasts use the one overlay glass alpha (#354 value, clearly see-through over a busy background), inner cards one step more opaque; keep 4.5:1 text contrast and prefers-reduced-transparency.
  • Evidence: production screenshots at 390/820/1440, light and dark, with a background picture behind the overlay and a toast shown over it; theme asserted before capture.
## Requests (owner, 2026-09-29) 1. "please make a single reusable card block for settings with extensible properties so it can be reused and one issue can be fixed easily!" 2. "the thing about settings being transparent along with more transparent toasts?" — the Settings overlay and toasts still look nearly opaque (screenshot: an almost white 'Link to "Text" copied' toast; Settings panel). #289/#354 asked for one overlay transparency, much more transparent, inner cards slightly more opaque; toasts use the same glass. 3. A toast detail the owner described a day ago ("the toast border line description") is not in any issue — waiting for the owner to restate it; add it here when they do. ## Build - **One Settings card block** in packages/ui (or apps/web settings/parts, whichever is the shared layer): `SettingsCard` with extensible props/snippets (title + LinkedHeading deep link, description, rows, footer actions, empty state, variants such as danger), and one `SettingsRow` (icon, title, chips, meta with tone, trailing actions, ⋯ menu, extra/full-width slot, stacking rules for narrow widths, icon centred on the text block). Migrate **every** Settings section to it (Account, Apps, Appearance, Editor, Notifications, Calendars, Mail, AI, Photos, Plugins, Maintenance, all Admin pages) and delete the per-section copies (SettingsGroup, AccountRow and ad-hoc rows fold into it). A guard test fails if a Settings section renders a card or row outside the shared block. - Shadows: keep the new `--glass-shadow-reach` rule (d0d83a32) inside the block's scroll parents. - **Transparency:** the Settings overlay surface and toasts use the one overlay glass alpha (#354 value, clearly see-through over a busy background), inner cards one step more opaque; keep 4.5:1 text contrast and `prefers-reduced-transparency`. - Evidence: production screenshots at 390/820/1440, light and dark, with a background picture behind the overlay and a toast shown over it; theme asserted before capture.
Author
Owner

Starting #402 on branch job/settings-card, based on d0d83a32b41e67b64f6586690ba4946e41878160.

Starting #402 on branch `job/settings-card`, based on `d0d83a32b41e67b64f6586690ba4946e41878160`.
Author
Owner

Finding: tokens.css already uses the #354 overlay alpha values (55% light, 38% dark), but keeps a second --glass-float-scrim-alpha for toasts above a scrim. Both values match today. I will route both through one overlay alpha token and retain the existing reduced-transparency opaque fallback and inner-card step.

Finding: `tokens.css` already uses the #354 overlay alpha values (55% light, 38% dark), but keeps a second `--glass-float-scrim-alpha` for toasts above a scrim. Both values match today. I will route both through one overlay alpha token and retain the existing reduced-transparency opaque fallback and inner-card step.
Author
Owner

Finding: the account-style row was also duplicated as one-off markup in Calendars (calendar colour/visibility rows), Mail (folder sync status), and Admin → Maintenance (expanded queue details). These now use SettingsRow; its iconless row covers calendar controls, and the full-width extra slot holds queue details. AccountList accepts a class so its shared list behavior can serve these nested rows.

Decision: SettingsCard and SettingsRow live in apps/web/src/routes/settings/parts. SettingsCard owns Settings deep links through the app's LinkedHeading; packages/ui/Card remains the shared material primitive.

Finding: the account-style row was also duplicated as one-off markup in Calendars (calendar colour/visibility rows), Mail (folder sync status), and Admin → Maintenance (expanded queue details). These now use `SettingsRow`; its iconless row covers calendar controls, and the full-width extra slot holds queue details. `AccountList` accepts a class so its shared list behavior can serve these nested rows. Decision: `SettingsCard` and `SettingsRow` live in `apps/web/src/routes/settings/parts`. `SettingsCard` owns Settings deep links through the app's `LinkedHeading`; `packages/ui/Card` remains the shared material primitive.
Author
Owner

Finding during production build: the Calendar nested account list now renders through shared AccountList, so local selectors .calendar-list and .calendar-list > li + li no longer cross the component boundary. Vite reported both as unused at CalendarsSection.svelte:392 and :398, which means the nested list spacing/container rule did not apply. I am making only those class selectors global and will rebuild before screenshots.

Finding during production build: the Calendar nested account list now renders through shared `AccountList`, so local selectors `.calendar-list` and `.calendar-list > li + li` no longer cross the component boundary. Vite reported both as unused at CalendarsSection.svelte:392 and :398, which means the nested list spacing/container rule did not apply. I am making only those class selectors global and will rebuild before screenshots.
Author
Owner

Preliminary adversarial finding (the server binary used here predates the latest dev merge): search_chaos.py expected HTTP 200 from the admin staged rebuild probe and received HTTP 202 with {"job_id":"514b18d8-7ff9-431e-82cb-cafe1b2fd034","inserted":true}. I left the existing assertion unchanged, as required, and will include this evidence for owner review. The first plugin round was invalid because its browser helper could not find the server binary and did not have the Photos fixture; I am rerunning the focused round against the merged build.

Preliminary adversarial finding (the server binary used here predates the latest dev merge): `search_chaos.py` expected HTTP 200 from the admin staged rebuild probe and received HTTP 202 with `{"job_id":"514b18d8-7ff9-431e-82cb-cafe1b2fd034","inserted":true}`. I left the existing assertion unchanged, as required, and will include this evidence for owner review. The first plugin round was invalid because its browser helper could not find the server binary and did not have the Photos fixture; I am rerunning the focused round against the merged build.
Author
Owner

Adversarial finding from the corrected round against the merged server: tests/adversarial/attack.py reported DAV probe finding: renamed tag page: missing source kinds: ['file', 'photo']. This is a tag-page inconsistency after rename; the probe did not report a server crash or 5xx for it. I am leaving the existing probe expectation unchanged and recording this for owner review because it is outside the Settings card change.

Adversarial finding from the corrected round against the merged server: `tests/adversarial/attack.py` reported `DAV probe finding: renamed tag page: missing source kinds: ['file', 'photo']`. This is a tag-page inconsistency after rename; the probe did not report a server crash or 5xx for it. I am leaving the existing probe expectation unchanged and recording this for owner review because it is outside the Settings card change.
Author
Owner

Adversarial finding from the same local round: tests/adversarial/attack.py sent a conditional DAV PUT with a VALARM component (BEGIN:VALARM, ACTION:DISPLAY, END:VALARM) and received HTTP 201; the existing probe marks any 2xx as accepted hostile input. I did not change the existing expectation. The write was confined to the throwaway local test server.

Adversarial finding from the same local round: `tests/adversarial/attack.py` sent a conditional DAV `PUT` with a `VALARM` component (`BEGIN:VALARM`, `ACTION:DISPLAY`, `END:VALARM`) and received HTTP 201; the existing probe marks any 2xx as accepted hostile input. I did not change the existing expectation. The write was confined to the throwaway local test server.
Author
Owner

The bounded round against the merged server completed its broad API probe and recorded these additional non-SLOW failures from existing probes; I did not change their expectations:

  • DAV discovery returned 207 but omitted calendar-home-set.
  • A Reminders VTODO PUT with an unsupported field returned 201; the probe expected 422.
  • Deleting the created VTODO returned 412; the probe expected 204.
  • An oversized Appearance request returned 502 (local adversarial server is unavailable); the probe expected 413.

The run also emitted load-only SLOW results. The changed User plugin toggle probe was run separately against this merged server and passed with zero findings and zero SLOW results. These DAV, Reminders and Appearance findings are outside the Settings card change and are recorded for owner triage.

The bounded round against the merged server completed its broad API probe and recorded these additional non-SLOW failures from existing probes; I did not change their expectations: - DAV discovery returned 207 but omitted `calendar-home-set`. - A Reminders VTODO PUT with an unsupported field returned 201; the probe expected 422. - Deleting the created VTODO returned 412; the probe expected 204. - An oversized Appearance request returned 502 (`local adversarial server is unavailable`); the probe expected 413. The run also emitted load-only SLOW results. The changed User plugin toggle probe was run separately against this merged server and passed with zero findings and zero SLOW results. These DAV, Reminders and Appearance findings are outside the Settings card change and are recorded for owner triage.
Author
Owner

Finished Forgejo #402 on branch job/settings-card.

Head: e0b2058ee4fe40980fea94c0aa3f9aa4bf2b2a9b (pushed; no merge to dev).

Built: Added shared SettingsCard and SettingsRow, migrated the Settings sections present at the single dev merge, removed their per-section card/row copies, added reuse guards and production screenshot automation, and kept card styling on role tokens. Reused packages/ui Card. The float alpha role now aliases the shared --glass-alpha source.

Files: apps/web/src/routes/settings/**; shared settings parts and guard/component tests; apps/web/e2e/settings-cards-402.mjs; packages/ui/src/tokens.css; tests/adversarial/attack2.py and tests/adversarial/run.sh.

Screenshots: 108 production captures (18 routes × 3 widths × 2 themes) are attached in six archives. They include a wallpaper and the runner asserts theme before capture.

Gates (verbatim logs attached): gate output archive

  • cargo fmt --check: exit 0; stdout and stderr empty.
  • cargo clippy --all-targets -- -D warnings: stopped before completion after 617 log lines to reserve time for web gates. No warning/error appeared in the recorded output.
  • cargo test: not run within the job time box.
  • bun run check: exit 0. Exact output:
    $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
    Text sizes use shared role tokens.
    Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/settings-card/apps/web
    Getting Svelte diagnostics...
    
    svelte-check found 0 errors and 0 warnings
    
  • bun run test: 123 files and 788 tests passed; one existing theme contract failed because --glass-float-scrim-alpha was absent. I kept the test unchanged and added that role as var(--glass-alpha). The focused contract then passed: Test Files 1 passed (1); Tests 1 passed | 71 skipped (72). The full suite was not rerun.

Adversarial: The new focused per-user plugin-toggle probe passed with zero findings and the server remained alive. The bounded broader round reported DAV, tag rename, VTODO, and oversized Appearance findings; their evidence and unchanged expectations are in earlier comments here. SLOW-only findings were load.

Known gaps: The #395 (Apps/App Passwords), #391 (Location), and #388 (Maintenance) section changes were absent at the one pre-gate dev merge. I did not merge dev a second time. Full workspace Clippy and cargo test remain incomplete.

Decisions: SettingsCard stays in the app because its heading uses the app's LinkedHeading; it composes the existing UI Card. The float compatibility token aliases the single overlay alpha rather than defining another value.

Finished Forgejo #402 on branch `job/settings-card`. **Head:** `e0b2058ee4fe40980fea94c0aa3f9aa4bf2b2a9b` (pushed; no merge to `dev`). **Built:** Added shared `SettingsCard` and `SettingsRow`, migrated the Settings sections present at the single `dev` merge, removed their per-section card/row copies, added reuse guards and production screenshot automation, and kept card styling on role tokens. Reused `packages/ui` Card. The float alpha role now aliases the shared `--glass-alpha` source. **Files:** `apps/web/src/routes/settings/**`; shared settings parts and guard/component tests; `apps/web/e2e/settings-cards-402.mjs`; `packages/ui/src/tokens.css`; `tests/adversarial/attack2.py` and `tests/adversarial/run.sh`. **Screenshots:** 108 production captures (18 routes × 3 widths × 2 themes) are attached in six archives. They include a wallpaper and the runner asserts theme before capture. - [Light 390](https://git.kayg.org/attachments/5ddde8a1-be36-453a-af21-e23b81c9e40a) - [Light 820](https://git.kayg.org/attachments/b8662733-f4b2-4692-b49c-3c5e81388985) - [Light 1440](https://git.kayg.org/attachments/aa11d4dd-7d2d-4e88-93f8-83e67c261792) - [Dark 390](https://git.kayg.org/attachments/eb6494db-504e-4150-9096-1b505c835a6e) - [Dark 820](https://git.kayg.org/attachments/1b05133f-3fd9-43cc-ab87-50e77a2a38b1) - [Dark 1440](https://git.kayg.org/attachments/d69ade61-ccad-41c4-8832-344677202567) **Gates (verbatim logs attached):** [gate output archive](https://git.kayg.org/attachments/cbde8f30-cd97-4399-a11c-866332212396) - `cargo fmt --check`: exit 0; stdout and stderr empty. - `cargo clippy --all-targets -- -D warnings`: stopped before completion after 617 log lines to reserve time for web gates. No warning/error appeared in the recorded output. - `cargo test`: not run within the job time box. - `bun run check`: exit 0. Exact output: ``` $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/settings-card/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` - `bun run test`: 123 files and 788 tests passed; one existing theme contract failed because `--glass-float-scrim-alpha` was absent. I kept the test unchanged and added that role as `var(--glass-alpha)`. The focused contract then passed: `Test Files 1 passed (1); Tests 1 passed | 71 skipped (72)`. The full suite was not rerun. **Adversarial:** The new focused per-user plugin-toggle probe passed with zero findings and the server remained alive. The bounded broader round reported DAV, tag rename, VTODO, and oversized Appearance findings; their evidence and unchanged expectations are in earlier comments here. SLOW-only findings were load. **Known gaps:** The #395 (Apps/App Passwords), #391 (Location), and #388 (Maintenance) section changes were absent at the one pre-gate `dev` merge. I did not merge `dev` a second time. Full workspace Clippy and `cargo test` remain incomplete. **Decisions:** `SettingsCard` stays in the app because its heading uses the app's `LinkedHeading`; it composes the existing UI Card. The float compatibility token aliases the single overlay alpha rather than defining another value.
Author
Owner

Starting #402 on branch job/settings-card. Worktree HEAD is e0b2058ee4; merge base with dev is c465150468. Incoming dev is 070c806cb5.

Starting #402 on branch job/settings-card. Worktree HEAD is e0b2058ee4fe40980fea94c0aa3f9aa4bf2b2a9b; merge base with dev is c46515046871936ad681c4d00e8b76de69dde3b7. Incoming dev is 070c806cb57de44d39105f0bbc5eb4c3dab2420d.
Author
Owner

Finding after the requested dev merge: the incoming Apps section still rendered its user and admin app-access lists through SettingsGroup, Card, and AccountRow. I migrated both branches through SettingsCard and SettingsRow and removed the duplicate AccountRow component. The App Passwords card now links to /settings/apps/app-passwords. No standalone Location or Maintenance section exists in this tree; the current precise-location option is in Appearance.

The first full web test run also found a token contract mismatch: commit e0b2058e defines --glass-float-scrim-alpha in packages/ui/src/tokens.css, while apps/web/src/lib/themes.test.ts requires that name to be absent. A repository search found only the definition and the assertion. The same run timed out RangeBar.svelte.test.ts:169 at 5 seconds (observed 5.7 seconds) while another worktree had a Vitest run active; I am treating that separately from the Settings migration and will preserve its expectation.

Finding after the requested dev merge: the incoming Apps section still rendered its user and admin app-access lists through SettingsGroup, Card, and AccountRow. I migrated both branches through SettingsCard and SettingsRow and removed the duplicate AccountRow component. The App Passwords card now links to /settings/apps/app-passwords. No standalone Location or Maintenance section exists in this tree; the current precise-location option is in Appearance. The first full web test run also found a token contract mismatch: commit e0b2058e defines --glass-float-scrim-alpha in packages/ui/src/tokens.css, while apps/web/src/lib/themes.test.ts requires that name to be absent. A repository search found only the definition and the assertion. The same run timed out RangeBar.svelte.test.ts:169 at 5 seconds (observed 5.7 seconds) while another worktree had a Vitest run active; I am treating that separately from the Settings migration and will preserve its expectation.
Author
Owner

Correction to my prior token finding: I removed the alias briefly to check the failing contract, then restored it. themes.test.ts calls glassAlpha("--glass-float-scrim-alpha") at line 252, which requires the token in tokens.css; the same file asserts that tokens.css must not contain the token name at line 290. The two expectations cannot both pass. I have kept the implementation and both test expectations unchanged; this needs the orchestrator owner to resolve. The independent full-suite RangeBar timeout remains a 5.7 s execution against a 5 s limit while another worktree was running Vitest; RangeBar and its test are identical on both merge parents.

Correction to my prior token finding: I removed the alias briefly to check the failing contract, then restored it. `themes.test.ts` calls glassAlpha("--glass-float-scrim-alpha") at line 252, which requires the token in tokens.css; the same file asserts that tokens.css must not contain the token name at line 290. The two expectations cannot both pass. I have kept the implementation and both test expectations unchanged; this needs the orchestrator owner to resolve. The independent full-suite RangeBar timeout remains a 5.7 s execution against a 5 s limit while another worktree was running Vitest; RangeBar and its test are identical on both merge parents.
Author
Owner

Transparency moves out of this issue: #436 now owns the glass material, including the see-through Settings overlay and toasts. #402 keeps the shared card and row block only.

Transparency moves out of this issue: #436 now owns the glass material, including the see-through Settings overlay and toasts. #402 keeps the shared card and row block only.
Author
Owner

Adversarial round finding for #402 (local server, merged tree):

  • The corrected ADVERSARIAL_API_ONLY=1 pass exited 1 with FINDINGS 249. Most findings were latency notes from the shared host. The run logged server alive at end: True.
  • Non-SLOW evidence: the cross-plugin Photos burst expected 120 uploaded Items and observed 112; several upload requests timed out at the probe's 30-second limit. Calendar Note/Log, Journal, template, Reminder and bookmark requests also timed out. The same host had other adversarial servers and several long-running Cargo builds. This was one bounded run; I did not repeat it.
  • The 3 MiB Appearance body probe got HTTP 502 with local adversarial server is unavailable through tests/adversarial/editor-proxy.mjs. The backend was still alive at the end. This does not establish whether the production server or only the test proxy caused the response.
  • The initial broad harness invocation lacked CALTERNAL_SERVER_BIN for helper processes and was stopped. The corrected API-only pass set both binary variables and completed.
  • In the broad attempt, search_chaos.py expected HTTP 200 for the staged rebuild request but got HTTP 202. The route's OpenAPI response in crates/calternal-server/src/wire.rs declares 202, matching the response. I left the existing probe assertion unchanged per the owner rule.

Please triage the timeout/202 observations before merge. No Rust or adversarial expectation changes were made in this job.

Adversarial round finding for #402 (local server, merged tree): - The corrected `ADVERSARIAL_API_ONLY=1` pass exited 1 with `FINDINGS 249`. Most findings were latency notes from the shared host. The run logged `server alive at end: True`. - Non-SLOW evidence: the cross-plugin Photos burst expected 120 uploaded Items and observed 112; several upload requests timed out at the probe's 30-second limit. Calendar Note/Log, Journal, template, Reminder and bookmark requests also timed out. The same host had other adversarial servers and several long-running Cargo builds. This was one bounded run; I did not repeat it. - The 3 MiB Appearance body probe got HTTP 502 with `local adversarial server is unavailable` through `tests/adversarial/editor-proxy.mjs`. The backend was still alive at the end. This does not establish whether the production server or only the test proxy caused the response. - The initial broad harness invocation lacked `CALTERNAL_SERVER_BIN` for helper processes and was stopped. The corrected API-only pass set both binary variables and completed. - In the broad attempt, `search_chaos.py` expected HTTP 200 for the staged rebuild request but got HTTP 202. The route's OpenAPI response in `crates/calternal-server/src/wire.rs` declares 202, matching the response. I left the existing probe assertion unchanged per the owner rule. Please triage the timeout/202 observations before merge. No Rust or adversarial expectation changes were made in this job.
Author
Owner

#402 complete

Branch: job/settings-card
Head SHA: b27bb57673f36ea49dc8f51921c980d5444bdcbe

Built

  • Migrated User and Instance Apps access cards and App Passwords to shared SettingsCard and SettingsRow components.
  • Ported the centered icon and narrow multi-action behavior into SettingsRow. A lone switch or button stays trailing in a card at or below 360 px.
  • Expanded the shared-component guard to scan all Settings views and verify User Apps, admin Apps, and App Passwords routes.
  • Added a production screenshot runner for all 52 registered Settings routes/groups and two legacy routes. Captured 312 route images at 390, 820 and 1440 px in light and dark themes, plus four 3× row crops.

Files changed for #402: apps/web/src/routes/settings/apps/AppsSection.svelte, apps/web/src/routes/settings/parts/SettingsRow.svelte, apps/web/src/routes/settings/shared-components.guard.test.ts, apps/web/e2e/settings-cards-402.mjs, and the merge resolution in apps/web/src/routes/settings/account/AppPasswordsGroup.svelte. Removed apps/web/src/routes/settings/parts/AccountRow.svelte.

Evidence

Local screenshots: artifacts/settings-card/sections/ (316 files, 18 MiB).
Download the attached screenshot bundle (14 MiB).

Production screenshot runner output:

PASS captured 312 Settings route screenshots and 4 3x row crops in /home/kayg/Developer/calternal-wt/settings-card/artifacts/settings-card/sections

The 3× crops show the icon centered against the title-plus-meta block and a lone switch trailing at 390 px.

Gates

bun run check (exit 0):

$ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes use shared role tokens.
[PLUGIN_TIMINGS] JavaScript callbacks ran for 3.8s of this 4.8s build (80%).
The slowest callbacks, timed inside each callback (the wait before a callback starts is excluded, the time it awaits is included):
  - plugin externalize-deps resolveId (80%, 3.8s, 4 calls)
See https://rolldown.rs/reference/InputOptions.checks#bundlertimings for more details.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/settings-card/apps/web
Getting Svelte diagnostics...
svelte-check found 0 errors and 0 warnings

bun run test (exit 1):

Test Files  2 failed | 124 passed (126)
Tests  2 failed | 801 passed (803)

Failures: src/lib/themes.test.ts both requires --glass-float-scrim-alpha to be defined and later asserts it is absent; src/lib/components/analytics/RangeBar.svelte.test.ts timed out at 5,000 ms (observed 5,705 ms). I left both existing expectations unchanged.

cargo build -p calternal-server (screenshot server): Finished dev profile [unoptimized + debuginfo] target(s) in 81m 08s. No Rust source changed, so Rust fmt/clippy/test gates were not run. Cleanup output: Removed 6940 files, 4.3GiB total. Removed apps/web/build and apps/web/.svelte-kit after capture.

Adversarial round and known gaps

The corrected, bounded ADVERSARIAL_API_ONLY=1 run exited 1 with FINDINGS 249; its final status was server alive at end: True. Most findings were SLOW responses on a host with concurrent adversarial servers and Cargo builds. Non-SLOW observations included 30-second request timeouts during the Photos upload storm, only 112 of 120 expected Photos Items observed, and a 502 for a 3 MiB Appearance body through the local test proxy. The backend was alive at the end. I posted the detailed evidence above and did not rerun the round.

The first broad invocation was stopped after its helper process could not find the server binary. In that attempt, search_chaos.py expected 200 for the staged rebuild but received 202. The route OpenAPI response in crates/calternal-server/src/wire.rs declares 202; I left the existing probe assertion unchanged. No security or hostile-input acceptance finding was observed in the corrected API pass.

Decisions

  • No standalone Location or Maintenance Settings section exists in this tree. The location control remains in Appearance; I did not create new sections.
  • App Passwords now link to /settings/apps/app-passwords, consistent with DESIGN §48. The legacy /settings/account/app-passwords route remains included in screenshot coverage.
  • Screenshot themes use the existing Paper light family and Catppuccin Mocha dark family.
## #402 complete Branch: `job/settings-card` Head SHA: `b27bb57673f36ea49dc8f51921c980d5444bdcbe` ### Built - Migrated User and Instance Apps access cards and App Passwords to shared `SettingsCard` and `SettingsRow` components. - Ported the centered icon and narrow multi-action behavior into `SettingsRow`. A lone switch or button stays trailing in a card at or below 360 px. - Expanded the shared-component guard to scan all Settings views and verify User Apps, admin Apps, and App Passwords routes. - Added a production screenshot runner for all 52 registered Settings routes/groups and two legacy routes. Captured 312 route images at 390, 820 and 1440 px in light and dark themes, plus four 3× row crops. Files changed for #402: `apps/web/src/routes/settings/apps/AppsSection.svelte`, `apps/web/src/routes/settings/parts/SettingsRow.svelte`, `apps/web/src/routes/settings/shared-components.guard.test.ts`, `apps/web/e2e/settings-cards-402.mjs`, and the merge resolution in `apps/web/src/routes/settings/account/AppPasswordsGroup.svelte`. Removed `apps/web/src/routes/settings/parts/AccountRow.svelte`. ### Evidence Local screenshots: `artifacts/settings-card/sections/` (316 files, 18 MiB). [Download the attached screenshot bundle](https://git.kayg.org/attachments/e9be5e91-d67c-4501-80d6-aa3f7e984492) (14 MiB). Production screenshot runner output: ```text PASS captured 312 Settings route screenshots and 4 3x row crops in /home/kayg/Developer/calternal-wt/settings-card/artifacts/settings-card/sections ``` The 3× crops show the icon centered against the title-plus-meta block and a lone switch trailing at 390 px. ### Gates `bun run check` (exit 0): ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. [PLUGIN_TIMINGS] JavaScript callbacks ran for 3.8s of this 4.8s build (80%). The slowest callbacks, timed inside each callback (the wait before a callback starts is excluded, the time it awaits is included): - plugin externalize-deps resolveId (80%, 3.8s, 4 calls) See https://rolldown.rs/reference/InputOptions.checks#bundlertimings for more details. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/settings-card/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` (exit 1): ```text Test Files 2 failed | 124 passed (126) Tests 2 failed | 801 passed (803) ``` Failures: `src/lib/themes.test.ts` both requires `--glass-float-scrim-alpha` to be defined and later asserts it is absent; `src/lib/components/analytics/RangeBar.svelte.test.ts` timed out at 5,000 ms (observed 5,705 ms). I left both existing expectations unchanged. `cargo build -p calternal-server` (screenshot server): `Finished dev profile [unoptimized + debuginfo] target(s) in 81m 08s`. No Rust source changed, so Rust fmt/clippy/test gates were not run. Cleanup output: `Removed 6940 files, 4.3GiB total`. Removed `apps/web/build` and `apps/web/.svelte-kit` after capture. ### Adversarial round and known gaps The corrected, bounded `ADVERSARIAL_API_ONLY=1` run exited 1 with `FINDINGS 249`; its final status was `server alive at end: True`. Most findings were `SLOW` responses on a host with concurrent adversarial servers and Cargo builds. Non-SLOW observations included 30-second request timeouts during the Photos upload storm, only 112 of 120 expected Photos Items observed, and a 502 for a 3 MiB Appearance body through the local test proxy. The backend was alive at the end. I posted the detailed evidence above and did not rerun the round. The first broad invocation was stopped after its helper process could not find the server binary. In that attempt, `search_chaos.py` expected 200 for the staged rebuild but received 202. The route OpenAPI response in `crates/calternal-server/src/wire.rs` declares 202; I left the existing probe assertion unchanged. No security or hostile-input acceptance finding was observed in the corrected API pass. ### Decisions - No standalone Location or Maintenance Settings section exists in this tree. The location control remains in Appearance; I did not create new sections. - App Passwords now link to `/settings/apps/app-passwords`, consistent with DESIGN §48. The legacy `/settings/account/app-passwords` route remains included in screenshot coverage. - Screenshot themes use the existing Paper light family and Catppuccin Mocha dark family.
Author
Owner

Correction to the final report: the route list contains 50 routes derived from the 20 registered Settings sections and their groups, plus 2 legacy routes, for 52 total routes. At 3 viewport widths and 2 themes, this is 312 full screenshots, plus 4 row crops.

Correction to the final report: the route list contains 50 routes derived from the 20 registered Settings sections and their groups, plus 2 legacy routes, for 52 total routes. At 3 viewport widths and 2 themes, this is 312 full screenshots, plus 4 row crops.
Author
Owner

Merged into dev and pushed (9bf3d549) after the web gates (816/816) and the relevant crate gates. Deploy follows the #356/#393 Apple GO/NO-GO.

Merged into dev and pushed (9bf3d549) after the web gates (816/816) and the relevant crate gates. Deploy follows the #356/#393 Apple GO/NO-GO.
kayg closed this issue 2026-09-29 15:47:34 +00:00
Sign in to join this conversation.
No labels
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
kayg/calternal#402
No description provided.