Commit Graph
100 Commits
Author SHA1 Message Date
Lucas BergerandClaude Sonnet 4.6 2fd253ea95 fix(20): WR-03 IN-03 phone sheet maxHeight scroll and safe-area padding
Add maxHeight:90dvh + overflowY:auto to the phone bottom-sheet branch
so content overflowing a short viewport (iPhone SE 667px) is scrollable
rather than clipped and the Save buttons remain reachable.

Add paddingBottom with env(safe-area-inset-bottom) to clear the iOS home
indicator / Android gesture navigation bar (IN-03).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 18:01:59 -04:00
Lucas BergerandClaude Sonnet 4.6 527d85530c fix(20): WR-01 WR-02 WR-04 profile mutation and handleClose fixes
WR-01: Send only changed fields in profileMutation so admin-toggle-only
saves don't re-send displayName (blocking members with null displayName
from ever having their admin flag toggled).

WR-02: Revert the toggle to member!.isAdmin explicitly instead of
`member?.isAdmin ?? true` — the prior fallback was correct by coincidence
but semantically wrong for any error path where member is non-null.

WR-04: Remove member-derived field resets (displayName, isAdmin) from
handleClose — those belong to the useEffect sync that already tracks
member?.id/displayName/isAdmin. Only ephemeral fields (passwords, errors)
are reset on close, eliminating the stale-closure Cancel regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 18:01:32 -04:00
Lucas BergerandClaude Sonnet 4.6 ee04aee4fb fix(20): CR-02 derive editorMember from live query data
Store only the member id in editorMemberId state rather than the full
AdminMember object. Derive editorMember from membersQuery.data after each
render, so query invalidations following a per-section save always give
MemberEditorSheet fresh server state — eliminating the stale-reference
silent-overwrite race.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 18:00:47 -04:00
Lucas BergerandClaude Sonnet 4.6 72977334fc fix(20): CR-01 WR-06 atomic last-admin guard + empty-body 400
Wrap the last-admin check and UPDATE in a db.transaction with a
SELECT...FOR UPDATE locking read so concurrent PATCH demotions
serialise and cannot both pass the guard, eliminating the TOCTOU
race (CR-01).

Add a .refine() to updateMemberSchema requiring at least one field,
returning 400 via noEchoHook instead of crashing Drizzle with an
empty SET clause (WR-06).

Add Test H asserting empty {} -> 400 { error: 'Invalid request' }.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:59:56 -04:00
Lucas Berger 5c74ada48b docs(20): add deep code review report 2026-06-18 17:57:08 -04:00
Lucas BergerandClaude Opus 4.8 f656a0c77b docs(phase-20): evolve PROJECT.md after phase completion
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:48:23 -04:00
Lucas BergerandClaude Opus 4.8 dec8220da3 docs(phase-20): complete phase execution — verification passed (9/9), advisory review
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:47:51 -04:00
Lucas Berger 80fd683877 docs(20-03): complete member editor + declutter plan 2026-06-18 17:40:52 -04:00
Lucas Berger 9b62887f0f feat(20-03): unify member editor + declutter admin members panel
- playwright-cli verified: Members tab shows tappable rows, no retired buttons
- Row tap opens 'Edit member' sheet; per-section saves keep sheet open
- 'Add member' trigger opens 'Add member' sheet in create mode
- Profile save fires 'Profile saved.' toast; sheet stays open (D-05)
- eslint + prettier + typecheck + vitest (275 tests) all pass
- Fix pre-existing prettier drift in docs/*, CLAUDE.md, README.md, api/admin.ts
2026-06-18 17:39:00 -04:00
Lucas Berger 9e6b004541 feat(20-03): rework AdminPage MemberRow + Add-member trigger; remove old surfaces
- MemberRow: whole-row role=button, aria-label='Edit {name}', trailing ChevronRight
- Admin badge on member.isAdmin (12px/600, --color-member-0 on --color-surface-dim)
- 'Add member' ghost trigger with Plus icon opens MemberEditorSheet in create mode
- Single MemberEditorSheet replaces CredentialSheet + ResetPasswordSheet mounts
- Removed: inline Local Accounts add-form, ResetPasswordSheet definition, create-form state
- Empty state: 'No members yet' / 'Add a member to get started.' (UI-SPEC copy)
2026-06-18 17:35:37 -04:00
Lucas Berger b125a69b58 feat(20-03): add MemberEditorSheet with edit/create modes and per-section saves
- Edit mode: Profile (display name + admin toggle), Set new password, App password sections
- Create mode: single form with display name, username, initial/confirm password
- Per-section saves keep sheet open; create success closes sheet (D-05, D-07)
- Admin toggle role=switch, aria-checked; last-admin 409 shows inline error + reverts (D-03)
- Section 2 gated on member.hasLocalCredential; passwords never prefilled (T-20-07)
- App password save routes through saveCredential -> CalDAV validation (T-20-08)
- No Rotate/Add credential/Reset password copy (D-06)
2026-06-18 17:31:46 -04:00
Lucas Berger 10149a5966 docs(phase-20): update tracking after wave 1 2026-06-18 17:23:49 -04:00
Lucas Berger 258a188bde chore: merge executor worktree (worktree-agent-af493496867aaca6d) 2026-06-18 17:21:59 -04:00
Lucas Berger b377e9cb0a chore: merge executor worktree (worktree-agent-afcc2c886302ea642) 2026-06-18 17:21:59 -04:00
Lucas Berger 4a179a943d docs(20-01): complete member-profile update plan — SUMMARY + all CI gates green 2026-06-18 17:21:30 -04:00
Lucas BergerandClaude Sonnet 4.6 618991cf13 docs(20-02): complete plan 20-02 summary
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:21:26 -04:00
Lucas BergerandClaude Sonnet 4.6 5bcd8180c1 feat(20-02): add updateMemberProfile fetcher + AdminMember.isAdmin
- Add isAdmin: boolean to AdminMember interface (after color, before
  hasCredential) — feeds the Phase 20 editor toggle initial state (D-02)
- Add updateMemberProfile(memberId, body) fetcher: PATCH /api/admin/members/:id,
  credentials:include, redirect:manual, JSON body
- Maps 401/opaqueredirect → SessionExpiredError (existing convention)
- Maps 409/422 → Error('last-admin') sentinel (D-03 last-admin guard)
- Maps other non-ok → generic error
- All 50 tests pass; eslint + prettier + tsc --noEmit exit 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:20:13 -04:00
Lucas Berger bc48632756 feat(20-01): add PATCH /members/:id member-profile update with last-admin guard
- Add isAdmin field to GET /members select and mapped member object (D-02)
- Add updateMemberSchema (displayName optional string, isAdmin optional boolean)
- Register adminRouter.patch('/members/:id') with noEchoHook and requireAdmin (inherited)
- Handler: parsePositiveIntParam id validation (400), existence check (404),
  D-03 last-admin guard via COUNT(*) query (409), partial set() update (200)
- Fix Test D: switch to adminId2 for GET after self-demotion (adminId1 no longer admin)
- All 44 tests green including 7 new PATCH/isAdmin tests
2026-06-18 17:19:43 -04:00
Lucas BergerandClaude Sonnet 4.6 18da7e9476 test(20-02): add failing tests for updateMemberProfile + AdminMember.isAdmin
- 8 RED tests covering: PATCH URL contract, credentials/redirect shape,
  void on 200, SessionExpiredError on 401/opaqueredirect, last-admin
  sentinel on 409 and 422, generic error on 500
- 1 compile-time shape test for AdminMember.isAdmin: boolean
- All new tests fail (updateMemberProfile is not a function); 42 existing pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 17:18:21 -04:00
Lucas Berger a0a82ac9b6 test(20-01): add failing tests for member-profile update + last-admin guard + isAdmin read
- Test A: PATCH displayName happy path → 200, GET reflects change
- Test B: PATCH isAdmin promote → 200, GET shows isAdmin true
- Test C: last-admin guard → 409 when only admin demotes self
- Test D: self-demotion → 200 when second admin exists
- Test E: non-admin PATCH → 403 (requireAdmin boundary)
- Test F: wrong-type body → 400 { error: "Invalid request" }; malformed :id → 400
- Test G: non-existent member id → 404
- Test H: GET /members includes boolean isAdmin per member
All 7 new tests fail RED for the right reasons (route 404 / isAdmin missing)
2026-06-18 17:18:14 -04:00
Lucas Berger 9b8b84edbe docs(20): finalize phase plan (state, roadmap waves, patterns) 2026-06-18 17:06:40 -04:00
Lucas Berger 666845a192 docs(20): create phase plan 2026-06-18 17:04:21 -04:00
Lucas Berger a3d89d0da0 docs(20): UI design contract 2026-06-18 16:51:46 -04:00
Lucas Berger 96193831c4 docs(20): UI design contract 2026-06-18 16:50:31 -04:00
Lucas Berger fe0325ec43 docs(state): record phase 20 context session 2026-06-18 16:42:23 -04:00
Lucas Berger 91948919a8 docs(20): capture phase context 2026-06-18 16:42:19 -04:00
Lucas Berger 51ec9c3e82 docs(roadmap): add Phase 20 — Admin Member Editor & Form Declutter 2026-06-18 15:14:25 -04:00
Lucas Berger b8d4a69b73 docs(phase-17): add security threat verification (9 closed, 0 open)
CI / changes (pull_request) Successful in 4s
CI / fast-checks (pull_request) Failing after 1m41s
CI / api (pull_request) Successful in 2m2s
CI / security (pull_request) Successful in 54s
CI / gate (pull_request) Has been cancelled
CI / harness (pull_request) Has been cancelled
2026-06-18 14:33:10 -04:00
Lucas Berger 881f2d2d18 test(17): complete UAT - 9 passed, 0 issues (playwright-cli verified) 2026-06-18 14:31:32 -04:00
Lucas Berger 6fa6725fe8 docs(17): add code review fix report (auto-loop, 3 iterations) 2026-06-18 14:06:03 -04:00
Lucas Berger 287ecae2f7 fix(17): CR-01 make focus-trap visibility filter tolerant of jsdom; IN-01 drop inert containment guard 2026-06-18 14:04:33 -04:00
Lucas Berger 89dee4f586 fix(17): IN-03 render visible Redirecting status during OIDC redirect 2026-06-18 13:57:31 -04:00
Lucas Berger f7575ea2c3 fix(17): IN-02 document hand-maintained favicon.ico coupling 2026-06-18 13:56:48 -04:00
Lucas Berger 7578d48d3d fix(17): IN-01 pull focus back into dialog when activeElement escapes 2026-06-18 13:56:32 -04:00
Lucas Berger 5b4625b41d fix(17): WR-01 exclude hidden/zero-size nodes from focus-trap boundaries 2026-06-18 13:56:23 -04:00
Lucas Berger 4bc1e2a820 fix(17): IN-05 normalize AdminPage JSX formatting with Prettier 2026-06-18 13:48:34 -04:00
Lucas Berger 11b6b36cb9 fix(17): IN-07 memoize Intl.DateTimeFormat timezone resolution 2026-06-18 13:47:37 -04:00
Lucas Berger 2317833b74 fix(17): IN-04 remove dead brand placeholder tokens 2026-06-18 13:46:47 -04:00
Lucas Berger 3f4b7eac73 fix(17): IN-02 useCallback handleClose, drop exhaustive-deps disables 2026-06-18 13:46:27 -04:00
Lucas Berger dd0b76128d fix(17): WR-08 replace cp icon chain with cross-platform Node copy script 2026-06-18 13:45:36 -04:00
Lucas Berger 1c0f35748d fix(17): WR-06 WR-07 clamp tz combobox active index; Tab-to-commit, blur-timer unmount cleanup 2026-06-18 13:44:44 -04:00
Lucas Berger f601c0c408 fix(17): WR-02 WR-03 WR-04 IN-06 admin tab Home/End+wrap; toast re-announce, wrap, z-index 400 2026-06-18 13:43:10 -04:00
Lucas Berger fb30800e9a fix(17): WR-01 trap focus in modal dialogs via useFocusTrap 2026-06-18 13:41:33 -04:00
Lucas Berger a4a7438641 fix(17): WR-05 IN-03 IN-01 resize-aware useIsPhone hook; OidcRedirect side-effect in effect 2026-06-18 13:40:00 -04:00
Lucas Berger c2ceebf130 docs(17): add deep code review report 2026-06-18 13:35:10 -04:00
Lucas BergerandClaude Opus 4.8 a986c74963 docs(phase-17): mark phase complete (pending human verification)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:11:35 -04:00
Lucas BergerandClaude Opus 4.8 fcc02e3833 docs(17): add phase verification report (10/10 decisions delivered; human_needed for device-only checks)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:11:23 -04:00
Lucas BergerandClaude Opus 4.8 9730d3dcdb docs(17): add code review report
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:06:20 -04:00
Lucas BergerandClaude Opus 4.8 ea49a4dc83 docs(phase-17): update tracking after wave 2
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:03:12 -04:00
Lucas BergerandClaude Opus 4.8 b5fcd1d172 fix(17): resolve post-merge wave 2 integration issues
- SettingsSheet: void the navigate('/login') promise (react-router v7 returns Promise) — eslint no-floating-promises
- InstructionSheet.test: wrap SettingsSheet render in MemoryRouter — 17-05 added useNavigate() which needs Router context

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:01:39 -04:00
Lucas Berger 4887ba1b5f chore: merge executor worktree (worktree-agent-a12887546a61a8053) 2026-06-18 12:58:59 -04:00
Lucas Berger aaf754d938 chore: merge executor worktree (worktree-agent-a65077bbd9885bf7e) 2026-06-18 12:58:58 -04:00
Lucas Berger 9e39a5c492 chore: merge executor worktree (worktree-agent-ad448992e936c77aa) 2026-06-18 12:58:57 -04:00
Lucas Berger 29f3d62312 chore: merge executor worktree (worktree-agent-a1f3ad1ab5d67e70c) 2026-06-18 12:58:56 -04:00
Lucas Berger f4c65d478a docs(17-06): complete admin polish plan — toasts + two-tab ARIA nav + e2e assertions 2026-06-18 12:58:06 -04:00
Lucas Berger 944045cd7e test(17-06): add admin two-tab ARIA and keyboard assertions to admin.spec.ts
- Add 'Admin two-tab ARIA strip (D-10)' describe block: tablist visible,
  both named tabs visible, ArrowRight/ArrowLeft keyboard switching,
  panel aria-labelledby, phone overflow check
- Add 'Admin success toast structure (D-08)' describe: role=status absent on load
- Satisfies Wave 0 admin-ARIA CI requirement — 12/12 tests pass on pixel profile
2026-06-18 12:56:34 -04:00
Lucas Berger caff8b4b0a docs(17-05): complete logout control + sheet centering plan
- Sign out control (D-07): LogOut icon, handleSignOut fire-and-best-effort, navigate /login
- Desktop centering (D-09): phone/desktop style branch on SettingsSheet, ChangePasswordSheet, LinkOidcSheet, CredentialSheet
- playwright-cli verified: centered modal @1280x720, bottom-sheet @390x844, Sign out redirects to /login
2026-06-18 12:54:43 -04:00
Lucas Berger 28e9ca9840 docs(17-03): complete phone layout overlap fix plan — SUMMARY.md
FAB lifted above BottomTabBar, phone content padding added, D-01
regression guard committed to layout.spec.ts; 3-profile e2e sweep green.
2026-06-18 12:54:30 -04:00
Lucas Berger 620d64138a feat(17-06): add success toasts to admin create-member and reset-password
- Add toast state + 3000ms auto-dismiss useEffect to AdminPage
- Set toast 'Member added.' in createMemberMutation.onSuccess
- Propagate 'Password reset.' up from ResetPasswordSheet via onSuccess callback
- Render role=status/aria-live=polite toast with CheckCircle icon
- Phone toast offset uses calc(var(--bottom-chrome-h) + var(--space-4)) to clear BottomTabBar
2026-06-18 12:53:12 -04:00
Lucas Berger b71238634f feat(17-05): add phone/desktop style branch to CredentialSheet (D-09)
- Add window.matchMedia('(max-width: 767px)') phone check
- Desktop branch: position fixed, top/left 50%, translate(-50%, -50%), maxWidth 480px, borderRadius 12px
- Phone branch: unchanged bottom-sheet (bottom 0, left 0, right 0, borderRadius 12px 12px 0 0)
- role=dialog, aria-modal, aria-label unchanged — only position CSS branched
- SettingsSheet, ChangePasswordSheet, LinkOidcSheet centering in prior commit (Task 1)
2026-06-18 12:52:59 -04:00
Lucas Berger 132a5e4eae feat(17-05): add Sign out control with handleSignOut to SettingsSheet (D-07)
- Add LogOut icon (lucide-react) and fetchLocalLogout (api/client) imports
- Add useNavigate (react-router) for post-logout redirect
- Implement handleSignOut: fire-and-best-effort try/catch, navigate to /login in both branches
- Add Sign out button row at bottom of sheet (44px tap target, var(--color-destructive), divider separator)
- Always navigates to /login even on API failure (server cookie cleared or expired)
2026-06-18 12:52:48 -04:00
Lucas Berger 4cb16f8271 docs(17-04): complete brand wiring plan — BrandSlot logo, favicons, maskable icon fix, accent
- BrandSlot: placeholder div replaced with decorative logo img (ce95aa3)
- tokens.css: --brand-logo-border-radius 0, --color-member-0 #e8915a (df578fd)
- index.html: favicon.svg + favicon.ico links, theme-color #e8915a (df578fd)
- vite.config.ts: maskable icon fixed to /icon-maskable-512.png, theme_color #e8915a (df578fd)
- Build: green; manifest.webmanifest verified correct
2026-06-18 12:51:58 -04:00
Lucas Berger 85a803fba6 test(17-03): add FAB↔BottomTabBar overlap regression guard to layout.spec.ts
- New test: "New Event FAB does not overlap BottomTabBar (A — phone only)"
- Skips on desktop profile; runs iphone + pixel (the profiles that exposed D-01)
- Asserts fabBox.y + fabBox.height <= navBox.y (FAB bottom ≤ bar top)
- Confirms Task 1 fix resolves the seed defect — passes green on both profiles
2026-06-18 12:51:32 -04:00
Lucas Berger df578fd7b7 feat(17-04): wire favicons + theme-color in index.html, fix maskable icon + accent in manifest
- index.html: add favicon.svg (SVG, modern browsers first) + favicon.ico (legacy) links
- index.html: update theme-color from #4A90D9 to approved #e8915a (warm amber)
- vite.config.ts: fix maskable icon — reference /icon-maskable-512.png (separate file) not /icon-512.png
- vite.config.ts: update manifest theme_color to #e8915a to match index.html
- tokens.css: update --color-member-0 to #e8915a (warm amber, Variant B, operator-approved 17-02)
- --sx-color-primary follows automatically via var(--color-member-0)
2026-06-18 12:50:50 -04:00
Lucas Berger ce95aa3e6b feat(17-04): wire logo img into BrandSlot, set --brand-logo-border-radius 0
- Replace placeholder FS div with decorative <img src="/logo.svg" alt="" aria-hidden>
- Apply Surface B-1 style (width/height brand-logo-size, borderRadius token, contain/block)
- Update --brand-logo-border-radius from 50% to 0 (SVG draws its own rx=104 shape)
- h1 FamilySync and tagline p unchanged; LoginPage.tsx untouched (seam contract honored)
- No dangerouslySetInnerHTML (T-05-24 invariant maintained)
2026-06-18 12:48:55 -04:00
Lucas Berger 5e1c714894 fix(17-03): lift FAB above BottomTabBar and reserve phone content padding
- CalendarShell.tsx: FAB bottom changed from var(--space-6) to
  calc(var(--bottom-chrome-h) + var(--space-6)) — sits 24px above bar
- App.tsx: contentStyle gains phone-only paddingBottom: var(--bottom-chrome-h)
  via spread pattern ...(phone ? {...} : {}) — desktop unchanged
2026-06-18 12:48:35 -04:00
Lucas Berger 9e080fb22a docs(phase-17): update tracking after wave 1 2026-06-18 12:45:49 -04:00
Lucas Berger 65e6222944 chore: merge executor worktree (worktree-agent-af89750bf86857964) 2026-06-18 12:44:24 -04:00
Lucas Berger 58d11caee0 chore: merge executor worktree (worktree-agent-a1fb88aa75fd00c8f) 2026-06-18 12:44:23 -04:00
Lucas Berger d917157c63 docs(17-02): complete branding assets plan summary
Records approved brand decisions for plan 17-04:
- logo art approved (family-house redesign)
- brand accent #e8915a (warm amber)
- --brand-logo-border-radius: 0
2026-06-18 12:43:45 -04:00
Lucas Berger 4c99470c1a feat(17-02): apply approved family-house logo + regenerate icon set
- Overwrite logo.svg with approved higher-contrast family-house SVG
  (warm peach gradient bg, amber roof, bold white walls, heart finial,
  three clearly-spaced family figures in rose/gold/blue)
- Regenerate full icon/favicon set from new art:
  favicon.svg, favicon.ico (967 B), icon-192.png (192x192),
  icon-512.png (512x512), icon-maskable-512.png (512x512 safe-zone),
  apple-touch-icon.png (180x180)
- Approved brand decisions recorded for plan 17-04:
  accent #e8915a, --brand-logo-border-radius: 0
2026-06-18 12:42:43 -04:00
Lucas Berger d01ec2388c docs(17-01): complete token groundwork plan — SUMMARY
tokens.css restructured to :root,[data-theme=light] combined selector;
--bottom-chrome-h added; all --sx-color-* overrides intact; build green;
layout.spec.ts pixel profile 15/15 pass; Schedule-X colors verified.
2026-06-18 12:14:45 -04:00
Lucas Berger b364573285 feat(17-02): generate full icon/favicon set from logo.svg (Task 2)
- Run @vite-pwa/assets-generator minimal2023Preset against public/logo.svg
- Produce: favicon.ico (861 B, non-trivial), favicon.svg, icon-192.png (1617 B),
  icon-512.png (4221 B), icon-maskable-512.png (3353 B, 512x512 distinct maskable
  with safe-zone padding), apple-touch-icon.png (1110 B, 180x180)
- Replace 3 placeholder stubs with real generated assets
- Update pwa:icons script to include post-generation canonical rename step
- Add generator intermediate output filenames to .gitignore
2026-06-18 12:13:50 -04:00
Lucas Berger c2f89bd55f feat(17-01): restructure tokens.css to combined :root,[data-theme=light] selector + add --bottom-chrome-h
- Change :root { to :root, [data-theme="light"] { (D-06 combined selector)
- Add --bottom-chrome-h: calc(56px + env(safe-area-inset-bottom, 0px)) to spacing scale
- Keep all 12 --sx-color-* overrides inside the combined block (cascade unchanged)
- Keep --brand-logo-* tokens inside the combined block (verbatim, no value changes)
- Add dark-theme stub as comment-only (Phase 999.20 fills values; no live rule)
- All existing values unchanged; PWA build passes; Schedule-X colors verified via playwright-cli
2026-06-18 12:12:42 -04:00
Lucas Berger 7db9005645 feat(17-02): install @vite-pwa/assets-generator, author logo.svg, add pwa-assets.config.ts
- Add @vite-pwa/assets-generator@1.0.2 as devDependency in apps/pwa
- Add pwa:icons script (pwa-assets-generator generate) to apps/pwa/package.json
- Approve sharp build scripts in pnpm-workspace.yaml (required for @vite-pwa/assets-generator)
- Hand-author apps/pwa/public/logo.svg: warm/rounded/at-home family scene with house, two adults, child, heart — square 512x512 viewBox, self-contained, text-free
- Create apps/pwa/pwa-assets.config.ts with minimal2023Preset, images: ['public/logo.svg'], no overrideManifestIcons
2026-06-18 12:12:17 -04:00
Lucas Berger eb0db8beef docs(17): create phase plan 2026-06-18 11:36:21 -04:00
Lucas Berger 280438b2d3 docs(17): create phase plan (6 plans, 2 waves) — UI optimization & polish 2026-06-18 11:34:04 -04:00
Lucas Berger 28cf79754a docs(17): add validation strategy 2026-06-18 11:19:24 -04:00
Lucas Berger f789a67f95 docs(17): research phase domain 2026-06-18 11:17:44 -04:00
Lucas Berger a1457a5b30 docs(17): UI design contract 2026-06-18 10:59:25 -04:00
Lucas Berger efeee02a36 Merge remote-tracking branch 'origin/main' into gsd/phase-17-ui-optimization-polish
# Conflicts:
#	.planning/STATE.md
2026-06-18 10:08:45 -04:00
Lucas BergerandClaude Opus 4.8 cfe84715d5 docs: add developer profile section to CLAUDE.md
Publish / publish (push) Successful in 11s
Generated by /gsd-profile-user from session analysis (8 dimensions).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 10:07:03 -04:00
Lucas Berger 1e2cc52659 docs: refresh project documentation against current codebase
Publish / publish (push) Successful in 26s
2026-06-18 06:44:29 -04:00
Lucas BergerandClaude Opus 4.8 b6490feff4 fix(19): satisfy CI fast-checks + secret scan
CI / changes (pull_request) Successful in 9s
CI / api (pull_request) Successful in 3m2s
CI / fast-checks (pull_request) Successful in 4m20s
CI / security (pull_request) Successful in 1m14s
CI / harness (pull_request) Successful in 6m56s
CI / gate (pull_request) Successful in 2s
Lint (eslint --max-warnings 0):
- index.ts: disable no-unsafe-argument on the type-only Context mismatch when
  delegating to the OIDC handler inside the local-session skip wrapper
- localAuth.ts: handleLogout is sync (no await) — drop async (require-await)
- devBypass.ts: disable detect-possible-timing-attacks on the public well-known
  dev-placeholder string compare (not a secret comparison)
- remove dead code / unused bindings flagged by no-unused-vars: makeTestApp
  (localSession.test), makeUnauthContext + BrowserContext import (login.spec),
  unused memberId (admin.test), unused txSelectCount counter (me.test)
- localAuthMiddleware.test / me.test: fix unused + reflow-detached
  eslint-disable directives

Format: prettier --write across the 20 Phase-19 files that were never formatted.

Secret scan (gitleaks): allowlist two false positives — the synthetic >=32-char
TEST_SECRET in localSession.test.ts, and .planning/ design prose (a generic-api-key
regex hit on "credential atomically, 409-equivalent"). Neither is a real secret.

Verified locally: format:check, lint, typecheck, md:lint, gitleaks (no leaks),
PWA 266/266, API 452/452.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 23:05:15 -04:00
Lucas Berger 91ab9d1f78 docs(19): ship phase 19 — PR #23 2026-06-17 22:49:45 -04:00
Lucas Berger abf7be782a docs(phase-19): add security threat verification (28/28 closed, threats_open: 0)
CI / changes (pull_request) Successful in 10s
CI / fast-checks (pull_request) Failing after 2m17s
CI / api (pull_request) Successful in 2m51s
CI / security (pull_request) Failing after 12s
CI / harness (pull_request) Successful in 5m9s
CI / gate (pull_request) Failing after 2s
2026-06-17 22:47:45 -04:00
Lucas Berger f3af130e9e docs(17): add workstream D — 4 UI findings from Phase 19 UAT (logout button, admin feedback, popup centering, admin nav) 2026-06-17 22:34:18 -04:00
Lucas Berger af0a70ccec test(19): complete UAT — Tests 1-3 pass live, 4 resolved-by-fix, 5→ship; 4 UI findings routed to Phase 17 2026-06-17 22:32:52 -04:00
Lucas Berger 73dd6a2383 docs(19): re-review after fixes — status clean (0 critical/warning, 2 info) 2026-06-17 20:50:25 -04:00
Lucas Berger 9cccf17ef9 chore: enable MemPalace discuss-time recall + KG mirror 2026-06-17 20:45:39 -04:00
Lucas Berger 5f74ae965d docs(19): add code review fix report 2026-06-17 20:42:51 -04:00
Lucas Berger cef2c66de5 merge(19): land code-review fixes (CR-01..04, BL-01..04, WR-01..07, IN-01..04) 2026-06-17 20:39:49 -04:00
Lucas Berger 2691dd0f95 fix(19): IN-04 enforce single-use OIDC-link nonce to prevent state replay 2026-06-17 20:37:09 -04:00
Lucas Berger 83e23d760d docs(state): record phase 17 context session 2026-06-17 20:37:02 -04:00
Lucas Berger 3784762817 docs(17): capture phase context (layout polish + branding + theme groundwork; dark mode/styling deferred) 2026-06-17 20:37:02 -04:00
Lucas Berger f02521dd02 fix(19): IN-03 evict stale loginAttempts entries to bound in-memory map growth 2026-06-17 20:35:43 -04:00
Lucas Berger e392bf2eb7 fix(19): IN-02 add lockstep test pinning inlined scrypt params against canonical verifyPassword 2026-06-17 20:34:58 -04:00
Lucas Berger f2fc1404d4 fix(19): IN-01 validate LOCAL_SESSION_EXPIRES coercion (fallback on NaN/non-positive) 2026-06-17 20:34:14 -04:00
Lucas Berger 916fb34f17 docs: add backlog items 999.20 (dark mode/theming) + 999.21 (styling refresh) 2026-06-17 20:34:02 -04:00
Lucas Berger 4bd6b2c057 fix(19): WR-05 add no-echo tests for admin create-member and me password hook sites 2026-06-17 20:33:46 -04:00