Files
collective-lists/docs/history/fase-1.md
Oier Bravo Urtasun 768b3cda58 docs: split CLAUDE.md into docs/{development,deployment,history/fase-*}
CLAUDE.md shrinks to rules + status + index (175 lines, down from 476).
Dev setup, prod deploy, and per-phase build records move to docs/.
Gotchas regrouped by domain (auth, frontend, PWA, testing, backend, deploy,
platform) and unnumbered so they don't drift as new ones land.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 22:21:20 +02:00

49 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fase 1 — what has been built
- `supabase/migrations/001_users.sql``users` table, `handle_new_user` trigger
- `supabase/migrations/002_collectives.sql``collectives`, `collective_members`, `collective_invitations`; auto-promote-oldest-admin trigger
- `supabase/migrations/003_rls.sql` — full RLS policies, `is_active_member`/`is_member`/`is_admin` helpers, `accept_invitation()` function
- `supabase/migrations/004_storage.sql``avatars` bucket (private, signed URLs)
- `apps/web/src/lib/supabase.ts` — Supabase singleton with PKCE flow
- `apps/web/src/lib/auth.ts``login()` / `logout()` via `supabase.auth.signInWithOAuth`
- `apps/web/src/lib/stores/auth.ts``currentUser`, `authLoading`, `isAuthenticated`, `displayName`
- `apps/web/src/lib/stores/collective.ts``currentCollective`, `userCollectives`, `collectiveMembers`
- `apps/web/src/lib/components/Avatar.svelte` — initials / emoji / upload with deterministic colour hash
- `apps/web/src/lib/components/ImageCropper.svelte` — lazy-loaded cropperjs, 1:1, 256×256 WebP output
- `apps/web/src/routes/+layout.svelte` — auth state listener, collective bootstrap
- `apps/web/src/routes/(app)/+layout.ts` — SSR disabled (`ssr: false`); no auth check here (see gotcha below)
- `apps/web/src/routes/(app)/+layout.svelte` — sidebar with collective switcher; auth redirect via `$effect`
- `apps/web/src/routes/auth/callback/+page.svelte` — PKCE code exchange
- `apps/web/src/routes/onboarding/+page.svelte` — create collective or join via link
- `apps/web/src/routes/(app)/collective/manage/+page.svelte` — members, roles, invite link generator
- `apps/web/src/routes/invitation/[token]/+page.svelte` — accept invitation (auth-aware)
- `apps/web/src/routes/(app)/settings/+page.svelte` — display name, avatar, language, sign out
- `apps/web/messages/en.json` + `es.json` — all Fase 1 + 2a strings
- `packages/types/src/database.ts` — manually seeded from migrations (update with `just db-types` once CLI is wired)
- `setup.sh` — idempotent local dev setup (prerequisites, .env, Docker, migrations, seed, Paraglide)
- `infra/kong-start.sh` — Kong container entrypoint; substitutes `${VAR}` placeholders in `kong.yml` before Kong starts (Kong 2.8 does not do this natively)
## Test suite — initial scaffolding
- `packages/test-utils/` — shared test infrastructure (Vitest integration tests)
- `package.json``@colectivo/test-utils`; depends on `@supabase/supabase-js`, `jose`, `pg`
- `vitest.config.ts` — loads root `.env` via `loadEnv`; single-fork mode (no parallelism races)
- `src/seed-constants.ts` — fixed UUIDs for all 5 seed users + collective + seed list
- `src/supabase-clients.ts``createClientAs(userId)` signs HS256 JWT with `SUPABASE_JWT_SECRET`; `createAdminClient()` uses service role key
- `src/db-helpers.ts``sql()` via raw `pg` Pool for direct DB manipulation (bypasses RLS); used to set `deleted_at = 8 days ago` etc.
- `tests/rls-isolation.test.ts` — F-series: Eva (non-member) sees zero rows, all writes blocked
- `tests/rls-collective.test.ts` — B-series: collective read/update/invite by role
- `tests/rls-lists.test.ts` — C-series: list CRUD, soft-delete, trash window, cross-collective isolation
- `tests/rls-items.test.ts` — D-series: item CRUD by role, cross-collective item isolation
- `tests/rls-frequency.test.ts` — E-series: frequency read-only + trigger populates on INSERT
- `supabase/tests/*.sql` each start with `CREATE EXTENSION IF NOT EXISTS pgtap;` so they're idempotent on a fresh DB
- `001_accept_invitation.sql``accept_invitation()` happy path + not_found / expired / already_used; uses `set_config('request.jwt.claim.sub', …)` to set `auth.uid()` for the test session, and looks up by `token` (not `id`)
- `002_item_frequency_trigger.sql` — trigger normalizes name with `lower(trim(...))` and increments `use_count` on repeat INSERTs. RLS write-blocks are covered by the Vitest suite instead (postgres superuser bypasses RLS here)
- `003_promote_on_admin_leave.sql` — deletes a synthetic admin from `public.users` to fire the `BEFORE DELETE` trigger and asserts the oldest remaining member is promoted
- `apps/web/playwright.config.ts` — Playwright config; `globalSetup` is a Keycloak health check (not a session cache), `reuseExistingServer: true`
- `apps/web/tests/fixtures/users.ts` — seed user constants (Ana, Borja, Carmen, David, Eva)
- `apps/web/tests/fixtures/login.ts``loginAs(page, user)` runs the real OAuth flow (Keycloak → GoTrue PKCE) and waits for the session token to land in localStorage. Each test that needs auth calls this in `beforeEach`; cached `storageState` is NOT used (see the Playwright storageState gotcha in `CLAUDE.md`)
- `apps/web/tests/e2e/auth.test.ts` — A-series: unauthenticated redirect, full login, collective visible in sidebar, sign-out, guest login
- `apps/web/tests/e2e/lists.test.ts` — C-series: create (with reload-persistence check), soft-delete → appears in trash drawer, archive, guest read-only
- `apps/web/tests/e2e/items.test.ts` — D-series: seed list renders, add item (with reload-persistence check), toggle check, desktop-hover delete, frequency suggestions, guest read-only