feat(fase-12): nav gating + redirect guard + realtime publication

UI side:
  * DesktopSidebar / BottomTabBar filter their entries by $enabledSections,
    tag each entry with data-section, and BottomTabBar exposes a
    data-section-count attribute so the grid is observable from tests.
  * "lists" is force-shown unconditionally — the §12.3.4 always-one-
    landing rule covers the edge case where every layer says OFF.
  * (app)/+layout.svelte adds a $effect that, when the URL matches a
    disabled section (/tasks, /notes, /search), goto's /lists and shows
    a transient `section_disabled_for_collective` toast.
  * Root +layout.svelte exposes the supabase singleton on window.__sb
    in dev so the new Playwright spec can patch rows without a parallel
    client; dead-code-eliminated in production builds.

DB side:
  * Migration 023 grows by ALTER PUBLICATION supabase_realtime ADD TABLE
    public.users + public.collectives + REPLICA IDENTITY FULL on both.
    Without this membership the features.ts subscriptions get zero
    events and SV-02 (collective toggle → realtime → member's nav
    updates) silently fails. Caught while running the spec.
  * pgTAP 015 grows from 16 to 20 assertions to cover publication
    membership + REPLICA IDENTITY for both new realtime tables.

Paraglide messages: section_disabled_for_collective, the visibility
section titles + blurbs, section_label_* per SectionKey. Both en + es.

Playwright tests/e2e/section-visibility.test.ts (SV-01..SV-03):
  SV-01 user toggle → nav reflects → /tasks redirects to /lists
  SV-02 admin collective toggle → member sees it disappear in realtime
  SV-03 collective ON beats user OFF — per-collective resolution

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 04:10:19 +02:00
parent 59c425f6f6
commit 286f59225f
9 changed files with 369 additions and 15 deletions

View File

@@ -95,3 +95,20 @@ COMMENT ON FUNCTION public.section_enabled(text, uuid, uuid) IS
'Effective ON/OFF of a top-level section for (user, collective). '
'Precedence: collective override > user override > default true. '
'Fase 13 will prepend a server-settings layer above the collective.';
-- ── Realtime ────────────────────────────────────────────────────────────────
-- The client-side `features.ts` store subscribes to `users` (own row) and
-- `collectives` (active row) so admin/user toggles propagate without a
-- reload. Without the publication membership those subscriptions receive
-- zero events — the realtime test (Playwright SV-02) was the catch.
--
-- REPLICA IDENTITY FULL is required so the OLD row carries all columns on
-- DELETE events; we only consume UPDATE here today, but `users` rows can be
-- deleted by the account-deletion flow (Fase 10.5) and a future Fase 13
-- "admin removes collective" will delete `collectives`. Filtering both
-- subscriptions still works correctly on DELETE this way.
ALTER PUBLICATION supabase_realtime ADD TABLE public.users;
ALTER PUBLICATION supabase_realtime ADD TABLE public.collectives;
ALTER TABLE public.users REPLICA IDENTITY FULL;
ALTER TABLE public.collectives REPLICA IDENTITY FULL;