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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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 Berger and Claude 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