Commit Graph

4 Commits

Author SHA1 Message Date
104eeba02e feat(fase-3): Tareas + Notas — TDD complete (148 tests green)
3.0 Tests primero
  pgTAP: 005_tasks_rls.sql (5 — completion CHECK), 006_notes_trash_purge.sql (4 — purge SQL inline + pin/archive CHECK)
  Vitest RLS: rls-tasks.test.ts (14), rls-notes.test.ts (15)
  Playwright: tasks.test.ts (3), notes.test.ts (4)

3.1 Tareas
  Migration 008_tasks.sql: task_lists + tasks + task_list_collective_id() helper
  CHECK constraint: is_completed ⇔ completed_by ⇔ completed_at
  RLS by role + cross-collective isolation
  Store apps/web/src/lib/stores/tasks.ts (optimistic CRUD + reorder)
  /tasks overview (grid + sticky create input + 5s polling)
  /tasks/[id] detail with svelte-dnd-action reorder, flip animation,
    inline edit (dblclick), "Completed by …" attribution via lazy-loaded
    collective_members

3.2 Notas
  Migration 009_notes.sql: notes + note_color enum (8) + pin/archive CHECK
    + 7d trash window in RLS + fn_notes_touch trigger + pg_cron purge job
  Store apps/web/src/lib/stores/notes.ts (CRUD + pin/archive/trash/duplicate)
  /notes board (pinned section testid notes-pinned + 30s polling)
  /notes/[id] editor (title + textarea, 500ms debounced autosave,
    color picker, pin/archive/duplicate/trash actions)
  /notes/archive (restore + send to trash)
  /notes/trash (restore + permanent delete)

3.Z Verification
  just test-all → 148 verdes, 2 skipped:
    25 pgTAP (was 16, +9)
    88 Vitest integration (was 59, +29; 2 presence skipped)
    6 Vitest unit (unchanged)
    29 Playwright (was 22, +3 tasks +4 notes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:28:19 +02:00
4c913cf495 feat(realtime): Fase 2b.0 infra + first R-series tests green
Enable postgres_changes broadcasts on shopping_items / shopping_lists and prove
the path end-to-end with Vitest Realtime tests and a pgTAP configuration check.

Infra changes that were silently blocking events
- Migration 007: shopping_items + shopping_lists added to supabase_realtime
  publication with REPLICA IDENTITY FULL (UPDATE/DELETE payloads need the full
  row so list_id-based filters work and RLS can evaluate DELETE against OLD)
- Realtime service: DB_USER=supabase_admin (superuser; supabase_replication_admin
  lacks CREATE on the `realtime` schema that the service auto-creates per tenant)
- Realtime service: SELF_HOST_TENANT_NAME=realtime so the seed tenant name
  matches the default supabase-js resolves for localhost URLs (was realtime-dev
  → TenantNotFound)

Tests
- pgTAP 004_realtime_publication.sql — P-01..P-04: publication membership and
  REPLICA IDENTITY FULL for both shopping tables
- Vitest realtime-postgres-changes.test.ts — R-01 INSERT broadcast,
  R-02 UPDATE carries full row, R-03 list_id filter isolates events
- test-utils realtime-helpers.ts — subscribePostgresChanges() returns a
  waitFor(predicate, timeout) helper that captures the SUBSCRIBED handshake
  before returning so mutations issued right after are not lost
- createClientAs now calls realtime.setAuth(token) so the server evaluates
  RLS against the test user's JWT
- Justfile test-db now globs supabase/tests/*.sql so new pgTAP files are picked
  up automatically

Totals: 54→57 Vitest, 12→16 pgTAP, 15 Playwright = 88 tests green.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 02:33:40 +02:00
3af1276c15 feat: Fase 2a — shopping lists CRUD
DB: shopping_lists + shopping_items tables with full RLS, pg_cron jobs
(archive completed lists after 7 days, purge trash after 7 days).
item_frequency table with SECURITY DEFINER trigger that normalises and
upserts on every shopping_items INSERT.

Frontend: /lists overview (featured card + 2-col grid + trash toggle),
/lists/[id] detail (qty stepper, inline edit, swipe-to-reveal-delete,
drag & drop reorder via svelte-dnd-action, ItemSuggestions chips).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 22:25:31 +02:00
7d91705fc2 feat(fase-1): auth, collective management, and DB migrations
- SQL migrations: users, collectives, collective_members, collective_invitations,
  full RLS policies, is_active_member/is_member/is_admin helpers,
  accept_invitation SECURITY DEFINER function, admin auto-promote trigger,
  avatars storage bucket
- Auth refactor: replace keycloak-js with Supabase OAuth (GoTrue OIDC proxy,
  Option B). signInWithOAuth({ provider: 'keycloak' }) + PKCE flow
- GoTrue config: GOTRUE_EXTERNAL_KEYCLOAK_URL + GOTRUE_EXTERNAL_KEYCLOAK_REDIRECT_URI
  added to docker-compose.dev.yml; Keycloak realm updated with GoTrue callback URI
- New routes: /auth/callback, /invitation/[token], /(app)/collective/manage
- Functional onboarding: create collective or join via invite link
- Full settings page: display name (debounced), avatar (initials/emoji/upload),
  language switcher, Keycloak account console link
- Components: Avatar.svelte (initials/emoji/upload with fallback),
  ImageCropper.svelte (cropperjs, 1:1 crop, lazy-loaded)
- i18n: added all Fase 1 message keys (en + es); renamed 'delete' → 'action_delete'
  (JS reserved word); fixed plugin-m-function-matcher major-version URL format
- Database types: manually seeded packages/types/src/database.ts from migrations
- .env.development: committed public dev defaults for SvelteKit type checking
- CLAUDE.md: documented /etc/hosts requirement for keycloak hostname

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 15:29:29 +02:00