diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 1df0ad0..76b4477 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -17,13 +17,19 @@ User screenshot: a basic active member filing an incident at `/incidents/new` (a - **DEPLOYED** as a minimal hotfix off `origin/main` (commit `1340b4c`, GitHub Actions run 25953569904 success, 1m0s; deploy.sh ran the idempotent migration runner so `025` applied): `scripts/025` re-asserts the hardened `incidents_insert` verbatim (access-neutral; fixes cause #2 only); `fileIncident` maps an RLS rejection to an actionable message and logs detail server-side. `scripts/schema.sql` already matched (no change). - **Still needs user verification:** retry filing an incident on prod. If it still fails, cause #2 is excluded; run the SQL below to confirm #1 vs #3. -### UX polish — Tier 1 minus S3 DEPLOYED +### UX polish — Tier 1 COMPLETE (S1-S8 deployed; S3 `108c2a5` local/unpushed); Tier 2/3 next - Full UI/UX audit done (5 partitioned agents, code-level; no live browser). User chose: implement Tiers 1-3, pause before 4-5; sidebar nav stays as-is (no role-filtering); comments get one-level nesting + edit (Tier 5, deferred). Findings report grouped Tier 1 systemic / 2 first-run / 3 security-adjacent / 4 brand / 5 per-surface. - Deployed commits (each was build+test green): `3360f54` sidebar/drawer a11y + distinct Ops icon + skip link + BrandMark; `92ba6fb` shared `PageTitle`/`SectionTitle` (21 files); `f885ac7` shared `Empty` (~18 states, projects gained one); `1db9434` shared accessible confirm (ConfirmProvider/useConfirm) replacing all 13 `window.confirm`; `075b274` `:focus-visible` ring (unlayered, in `app/globals.css`) + 44px tap targets at named hotspots + 28 form-field id/htmlFor + search aria-labels + claim/complete/delete/link handlers toast `result.error`. Plus preexisting `fa71d9a` (a prior HANDOFF doc, not this session) and doc commits. - **Not browser-verified (no live browser this session):** smoke-test on prod the two behavior-changing pieces — the shared confirm dialog on every destructive action (delete member/role/tier/area/invite/onboarding-step/secret/KB/comment/project/contact/thread) and the mobile drawer (open/ESC/scroll-lock/focus); also eyeball the global focus ring and the dense-row tap-target `-my-2` spacing. -- **Tier 1 remaining = S3 only:** convert hand-rolled modals to the existing Radix `components/ui/dialog.tsx` (focus trap/ESC/aria for free). Targets: `ops/ops-client.tsx` (4: KbModal, AddSecretModal, AreaLeadModal, KB-view), `members/tasks/projects/payments/contacts-client.tsx` (1 add/edit modal each), `settings/settings-client.tsx` (integration-credentials modal ~569-660). Each is a `fixed inset-0` div with local open-state; swap to `` + `DialogContent`, keep the form/handlers verbatim. Do modal-by-modal with a build+test gate per group. -- **Tier 2** (founder first-run guided dashboard when the space is empty; onboarding Skills controlled value + required-ack hint) and **Tier 3** (secrets copy + auto re-hide + clear-on-unmount; permissions matrix read-only notice + per-checkbox aria-label; OpsAclEditor `aria-pressed`/check/toast) not started. Tier 3 is presentational-only and must stay inside the RLS guardrail (no change to reveal action, `user_has_permission`, `ops_acl`, self-change trigger). +- **Tier 1 COMPLETE.** S3 done in commit `108c2a5` (LOCAL, unpushed): every hand-rolled modal converted to Radix `components/ui/dialog.tsx` (focus trap/ESC/aria) — ops (4), members/tasks/projects/contacts add-edit, settings integration-credentials, plus the payments Log-Cash AND Link-Member modals. Forms/handlers/validation/close-reset preserved; `onOpenChange` mirrors old Cancel/X. Build clean, 271/271. 0 residual `fixed inset-0` modal overlays. Not browser-verified: smoke-test each modal opens/submits/ESC-closes. +- **Tier 2 (next, not started):** founder first-run guided dashboard when the space is empty (`app/(app)/dashboard/page.tsx`); onboarding Skills controlled value + required-ack hint (`app/onboarding/onboarding-flow.tsx`). +- **Tier 3 (after Tier 2):** secrets copy + auto re-hide + clear-on-unmount; permissions matrix read-only notice + per-checkbox aria-label; OpsAclEditor `aria-pressed`/check/toast. Presentational-only, must stay inside the RLS guardrail (no change to reveal action, `user_has_permission`, `ops_acl`, self-change trigger). +- Sequence: finish Tier 2 + Tier 3, deploy, THEN the forms feature. + +### Forms + waivers feature (designed 2026-05-16, build deferred until after polish Tiers 1-3) + +Full design delivered in chat. Locked decisions: anonymous waivers allowed (capture IP/UA/timestamp; retro-link to a later account only on verified email; admin manual-link for mismatches); non-blocking re-sign on waiver version bump (old signatures stay valid against their snapshot). User guidance: waivers are the primary need but the feature must also support ANY arbitrary form with a VERY EASY designer (builder ergonomics are an explicit priority). Recommended defaults: global-unique slug `/f/[slug]`; reuse `space_onboarding_steps` for an onboarding `form` step; gate creation via `lib/permissions-catalog.ts` (`forms.manage`) + `user_has_permission`; funnel anon submissions through one validated server action + service client (pattern: `finishOnboarding`); snapshot schema+legal-text per submission for immutable waiver records. Two new tables (`forms`, `form_submissions`); the anon-write + retro-link + immutability RLS is security/legally sensitive — design under the guardrail. Memory: `forms-feature` / `hackerspace-rls-guardrail`. ### Pending decision / next step