2174d2c2c0
feat(fase-5): mobile UX shell + masthead + swipe-delete undo (224 tests green)
...
5.0 Tests primero
Playwright: mobile-shell.test.ts (4 — sidebar hidden on mobile, bottom tab
bar visible with aria-current, hamburger opens drawer, desktop shows
sidebar), mobile-masthead.test.ts (4 — every top-level route pairs
masthead-label + masthead-title), mobile-swipe-delete.test.ts (M-06/M-07
describe.skip — Chromium touch emulation flaky; needs `playwright install
webkit`)
Vitest: undoQueue.test.ts (5 — schedule+commit, undo+restore, TTL expiry,
double-undo no-op, custom ttlMs)
5.1 Responsive shell
DesktopSidebar.svelte (hidden md:flex)
MobileTopBar.svelte (md:hidden sticky backdrop-blur-xl)
BottomTabBar.svelte (md:hidden glassmorphism, safe-area-inset-bottom)
MobileDrawer.svelte (backdrop + collective switcher + settings + logout)
(app)/+layout.svelte — CRITICAL FIX: flex flex-col md:flex-row. Was
horizontal-only, which pushed masthead off-screen on mobile. UndoToast
mounted globally here.
5.2 Masthead + responsive padding
ScreenMasthead.svelte — label (13px uppercase) + title (26px/32px).
Applied to /lists, /tasks, /notes, /search. px-8 → px-4 md:px-6 everywhere.
messages/{en,es}.json: masthead_{lists,tasks,notes,search}_label +
masthead_search_title, undo, undo_deleted_item, list_item_delete_aria.
5.4 Red-zone swipe-delete on /lists/[id]
SWIPE_MAX=96 (red zone rest width), SWIPE_THRESHOLD=48 (latch-open),
SWIPE_COMMIT_THRESHOLD=200 (full-swipe commit). Red zone button exposes
aria-label="Delete item"/"Eliminar producto". handleDelete uses
scheduleUndoable — optimistic local removal, 4-s TTL, commit to Supabase
on timeout or restore from snapshot on Undo.
5.5 UndoQueue + UndoToast
src/lib/sync/undoQueue.ts — writable store + Map-backed actions with TTL.
__flushUndoQueueForTests + __pendingUndoCount for Vitest.
src/lib/components/UndoToast.svelte — renders latest undoable, offset
above bottom tab bar (bottom: calc(env(safe-area-inset-bottom) + 4.5rem)),
Undo button.
5.6 Scrollable frequency chips
ItemSuggestions.svelte — mobile: flex overflow-x-auto with
[scrollbar-width:none] [&::-webkit-scrollbar]:hidden; desktop: wraps.
Chips shrink-0 so they don't compress.
5.7 Shell polish on tasks/notes/search
Search group headers now carry "{n} MATCH / MATCHES" badges.
Grid in /lists goes 2-col → 3-col at md+.
Sticky create input offset for the bottom tab bar on mobile.
5.Z Verification
just test-all → 224 verdes, 4 skipped
34 pgTAP (unchanged)
140 Vitest integration + 2 skipped presence (unchanged)
11 Vitest unit (was 6, +5 undoQueue)
39 Playwright + 2 skipped swipe-touch (was 31, +8 new mobile tests)
Deferred (explicitly):
- Presence avatars + item counts on list cards (needs per-list count RPC)
- Integrate undoQueue in task delete + note trash (trivial when needed)
- WebKit install to unskip M-06/M-07 swipe gesture tests
- max-w-2xl reading-width constraint on notes/search
- Manual visual QA in DevTools iPhone/Pixel/Desktop viewports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-13 14:09:17 +02:00
2806e06db2
feat(fase-4): global search + RLS isolation audit (211 tests green)
...
4.0 Tests primero
Vitest: search.test.ts (10 — S-01..S-04), rls-audit.test.ts (42 —
3 intruders × 14 cross-collective ops proving zero leakage)
pgTAP: 007_search_tsvector.sql (9 — columns, GIN indexes, function
signature, generated-vector invariant)
Playwright: search.test.ts (2 — SR-01 happy-path, SR-02 filter toggle)
4.1 Búsqueda global
Migration 010_search_vectors.sql: STORED GENERATED tsvector columns
on shopping_items/tasks/notes + GIN indexes + search_result_type
enum + search_in_collective() SECURITY INVOKER function (RLS-aware,
trash-excluded per RN-08) + GRANT EXECUTE to anon/authenticated.
Uses `simple` config (no stemmer — bilingual en/es).
Store apps/web/src/lib/stores/search.ts — RPC wrapper
/search: debounced input (300ms, ≥2 chars), type filter chips with
multi-toggle, results grouped per type with data-testid hooks for
Playwright, deep-link per type (shopping_item → /lists/[id], task →
/tasks/[id], note → /notes/[id])
4.4 Security
rls-audit.test.ts replaces the curl-based manual audit with a
parametrised matrix — zero cross-collective reads/writes under
three different attacker roles
Realtime flake hardening
Add 250ms settle after SUBSCRIBED in realtime-helpers.ts — the Phoenix
socket reports SUBSCRIBED slightly before the backend finishes
propagating the filter to the WAL subscription, so mutations fired
immediately after subscribe could miss the filter under load.
4.Z Verification
just test-all → 211 verdes, 2 skipped
34 pgTAP (was 25, +9 search)
140 Vitest integration (was 88, +10 search +42 rls-audit; 2 skipped)
6 Vitest unit (unchanged)
31 Playwright (was 29, +2 search)
Deferred (prod-deploy scope):
PWA install/push (needs real iOS/Android hardware)
Kong rate-limit plugin config
JWT_SECRET / ANON_KEY rotation
Lighthouse PWA ≥ 90 manual validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-13 12:47:38 +02:00
ce1bcfb7a6
feat(design): apply Monolith Editorial design system to all Fase 1 screens
...
- Remove all 1px border separators (sidebar border-r, page header border-b,
section border-t, member list divide-y, invite card border). Separation is
now achieved via background color shifts and whitespace per the "No-Line" rule.
- Fix sidebar: bg-surface-raised vs bg-background creates tonal separation.
- Correct dark background to #020617 (slate-950) per spec.
- Add surface-container-low, text-primary/secondary/muted, destructive tokens.
- Fix CSS variable color space: all tokens are RGB triplets; switch Tailwind
config and app.css from hsl() to rgb() to prevent yellow/warm color bleed.
- Replace emoji nav icons with Lucide icons at 16px / 1.5 stroke-width.
- Apply Masthead typography (uppercase Label-MD + Title-LG) to all page headers
and section labels across lists, tasks, notes, search, settings, manage.
- Destructive action (sign out) uses bg-destructive per spec.
- Add `just serve` command: builds and runs the prod Node server at :3000
against the dev Docker stack for production build testing.
- Add nav_collective i18n key (en + es).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-12 22:09:25 +02:00
973f9e413c
Fase 0: scaffold monorepo, SvelteKit skeleton, and dev infrastructure
...
- Turborepo + pnpm workspaces with apps/web and packages/types
- SvelteKit app: Tailwind, Paraglide i18n (en/es), keycloak-js, Supabase client,
auth/collective stores, PWA service worker skeleton, all route placeholders
- packages/types: domain types (User, Collective, ShoppingList, etc.) and
database.ts placeholder for generated types
- Justfile with dev, db-*, kc-*, build, backup, restore, deploy recipes
- infra/docker-compose.dev.yml: Postgres 15, GoTrue, PostgREST, Realtime v2.83,
Storage, Kong (port 8001), Studio, Keycloak 24
- infra/docker-compose.prod.yml, kong.yml, db-init scripts, backup/deploy scripts
- keycloak/realm-export.json with colectivo realm and 5 dev test users
- supabase/config.toml and seed.sql with sample collective and items
- GitHub Actions: ci.yml (lint+typecheck+build) and deploy.yml (GHCR + SSH)
- .env.example documenting all required variables
- Fixed docker-compose issues: Studio image tag, Kong port conflict (8001),
internal role passwords init script, Realtime METRICS_JWT_SECRET/APP_NAME
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-12 14:37:51 +02:00