docs(mvp2): close out — 7/7 fases shipped, 497 tests green
Fase 15 (common items management) lands; MVP2 cycle complete.
Final test totals after MVP2 (Fase 9 → 15):
- pgTAP: 177 (was 45 → +132)
- Vitest integration: 179 (was 140 → +39)
- Vitest unit: 47 (was 15 → +32)
- Playwright e2e: 93 (was 59 → +34)
- Rate-limit gated: 1
- Total active: 497 (was 259 → +237)
- Skipped: 3 (unchanged)
Migrations 015 → 026 (12 new). pgTAP 009 → 018 (10 new files).
Per-fase history docs under docs/history/fase-{9,10,11,12,13,14,15}-*.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -6,9 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
**Fase 0–5 complete. Fase 6 complete (deploy readiness: PWA injectManifest SW + manifest + iOS meta tags + placeholder icons + Kong rate-limit on invitations + dev JWT rotation + prod env template + rls-audit.sh + Justfile lighthouse/rls-audit/test-rate-limit). Production stack deployed to ambrosio (OVH VPS) at https://erosi.limonia.net (app + Supabase, external Keycloak); edge proxy now off-stack — internal Caddy fans kong/app on host port 3000, whatever external proxy fronts the host terminates TLS and forwards plain HTTP to ambrosio:3000 (originally NetBird's self-hosted Traefik, now proxy-agnostic); PWA strategy switched to generateSW to unblock the prod build (see the "injectManifest hardcoded filename" gotcha below). Fase 7 complete: 12 new Playwright tests fill the collective-flow UI gap (O-01..O-03 onboarding, I-01..I-05 invitation acceptance, MC-02..MC-05 admin-manage) — writing them surfaced + fixed three latent bugs in the product code (atomic `create_collective()` RPC, pendingInvitationToken restore after login, manage page not reloading on late $currentCollective hydration). Plus migration 013 (auth.users role/aud default trigger) — found after the first real self-registration on prod via Keycloak→GoTrue left the user with empty `role`/`aud` columns, breaking every REST call with `role "" does not exist`. Post-fase-7 prod auth hardening (2026-04-20..21, see `docs/history/fase-8-auth-logout.md`): migration 014 extends the role/aud guard to UPDATE (GoTrue's pop-ORM resends role='' right after the INSERT and clobbered the INSERT trigger's backfill); `logout()` now does RP-initiated Keycloak end-session + lands on a new public `/logged-out` route, which both actually ends the Keycloak SSO cookie (so the next login re-prompts) and closes a PKCE-verifier race that produced "PKCE code verifier not found in storage" on prod. 259 tests green: 45 pgTAP + 140 Vitest integration + 15 Vitest unit + 59 Playwright + 1 Vitest rate-limit (gated, run via `just test-rate-limit`). 3 skipped in `just test-all` (2 Realtime presence — upstream `handle_out/3` bug; 1 rate-limit — gated). Push notifications + CI Docker + final production icons deliberately out of scope. ✅**
|
**Fase 0–5 complete. Fase 6 complete (deploy readiness: PWA injectManifest SW + manifest + iOS meta tags + placeholder icons + Kong rate-limit on invitations + dev JWT rotation + prod env template + rls-audit.sh + Justfile lighthouse/rls-audit/test-rate-limit). Production stack deployed to ambrosio (OVH VPS) at https://erosi.limonia.net (app + Supabase, external Keycloak); edge proxy now off-stack — internal Caddy fans kong/app on host port 3000, whatever external proxy fronts the host terminates TLS and forwards plain HTTP to ambrosio:3000 (originally NetBird's self-hosted Traefik, now proxy-agnostic); PWA strategy switched to generateSW to unblock the prod build (see the "injectManifest hardcoded filename" gotcha below). Fase 7 complete: 12 new Playwright tests fill the collective-flow UI gap (O-01..O-03 onboarding, I-01..I-05 invitation acceptance, MC-02..MC-05 admin-manage) — writing them surfaced + fixed three latent bugs in the product code (atomic `create_collective()` RPC, pendingInvitationToken restore after login, manage page not reloading on late $currentCollective hydration). Plus migration 013 (auth.users role/aud default trigger) — found after the first real self-registration on prod via Keycloak→GoTrue left the user with empty `role`/`aud` columns, breaking every REST call with `role "" does not exist`. Post-fase-7 prod auth hardening (2026-04-20..21, see `docs/history/fase-8-auth-logout.md`): migration 014 extends the role/aud guard to UPDATE (GoTrue's pop-ORM resends role='' right after the INSERT and clobbered the INSERT trigger's backfill); `logout()` now does RP-initiated Keycloak end-session + lands on a new public `/logged-out` route, which both actually ends the Keycloak SSO cookie (so the next login re-prompts) and closes a PKCE-verifier race that produced "PKCE code verifier not found in storage" on prod. 259 tests green: 45 pgTAP + 140 Vitest integration + 15 Vitest unit + 59 Playwright + 1 Vitest rate-limit (gated, run via `just test-rate-limit`). 3 skipped in `just test-all` (2 Realtime presence — upstream `handle_out/3` bug; 1 rate-limit — gated). Push notifications + CI Docker + final production icons deliberately out of scope. ✅**
|
||||||
|
|
||||||
**MVP2 — in progress (6/7 ✅).** Branch `mvp2`. Original cycle (fases 9–14) shipped 2026-05-18; ciclo reabierto con **Fase 15** añadida después. **Fase 9: dark mode + polish** (migrations 015–016 + pgTAP 009–010 + dark-mode plumbing + max-w-2xl reading column + sync_conflicts table/queue logging + WebKit Playwright project; see `docs/history/fase-9-polish-dark-mode.md`). **Fase 10: spec completion (H06/H07/H08 + trash restore + account deletion + sidebar-create + reset-from-detail + Accept-Language)** — migrations 017–021 + 4 new pgTAP suites + 6 new Playwright specs; see `docs/history/fase-10-spec-completion.md`. **Fase 11: item tags + drag-reorder** — migration 022 + pgTAP 014 + tags store + chips/picker + filter bar + realtime re-sort; see `docs/history/fase-11-item-tags-importance.md`. **Fase 12: section visibility (feature flags)** — migration 023 + pgTAP 015 + JSONB `feature_flags` on `users`+`collectives` + `public.section_enabled()` SQL helper with COALESCE precedence; see `docs/history/fase-12-section-visibility.md`. **Fase 13: server administration** — migrations 024+025 (server_admins + admin_actions + server_settings + 9 SECURITY DEFINER admin RPCs) + pgTAP 016+017 + `/admin` route group + last-admin guard + audit-append-only via missing-policies pattern + `section_enabled()` extended with server layer + `SERVER_ADMIN_EMAIL` bootstrap (prod needs manual re-run after the operator's first Keycloak login); see `docs/history/fase-13-server-admin.md`. **Fase 14: PWA hardening** — `useRegisterSW` + `UpdateToast` (auto-update toast) + offline chip + queued-op badge + `/settings/sync-conflicts` review route + `__APP_VERSION__`/`__APP_COMMIT__`/`__BUILD_TIME__` defines baked at build via Dockerfile `GIT_SHA` build-arg (host-side `git rev-parse --short HEAD` in `deploy-erosi.sh`) + "Acerca de" version chip in `/settings`; no migration; see `docs/history/fase-14-pwa-hardening.md`. **Final test totals (`just test-all`): 166 pgTAP + 173 Vitest integration + 47 Vitest unit + 89 Playwright + 1 gated rate-limit = 476 tests green; 3 skipped (2 Realtime presence — upstream `handle_out/3` bug `supabase/realtime#1617`; 1 rate-limit — gated). Delta vs MVP close: +121 pgTAP + +33 integration + +32 unit + +30 e2e = +217 tests across MVP2 fases 9–14.** Fase 7+8 already shipped as MVP cleanup, not MVP2.
|
**MVP2 — COMPLETE (7/7 ✅, 2026-05-18).** Branch `mvp2`. Original cycle (fases 9–14) shipped 2026-05-18; **Fase 15 (common items management)** shipped same day after reopening the cycle. **Fase 9: dark mode + polish** (migrations 015–016 + pgTAP 009–010 + dark-mode plumbing + max-w-2xl reading column + sync_conflicts table/queue logging + WebKit Playwright project; see `docs/history/fase-9-polish-dark-mode.md`). **Fase 10: spec completion (H06/H07/H08 + trash restore + account deletion + sidebar-create + reset-from-detail + Accept-Language)** — migrations 017–021 + 4 new pgTAP suites + 6 new Playwright specs; see `docs/history/fase-10-spec-completion.md`. **Fase 11: item tags + drag-reorder** — migration 022 + pgTAP 014 + tags store + chips/picker + filter bar + realtime re-sort; see `docs/history/fase-11-item-tags-importance.md`. **Fase 12: section visibility (feature flags)** — migration 023 + pgTAP 015 + JSONB `feature_flags` on `users`+`collectives` + `public.section_enabled()` SQL helper with COALESCE precedence; see `docs/history/fase-12-section-visibility.md`. **Fase 13: server administration** — migrations 024+025 (server_admins + admin_actions + server_settings + 9 SECURITY DEFINER admin RPCs) + pgTAP 016+017 + `/admin` route group + last-admin guard + audit-append-only via missing-policies pattern + `section_enabled()` extended with server layer + `SERVER_ADMIN_EMAIL` bootstrap (prod needs manual re-run after the operator's first Keycloak login); see `docs/history/fase-13-server-admin.md`. **Fase 14: PWA hardening** — `useRegisterSW` + `UpdateToast` (auto-update toast) + offline chip + queued-op badge + `/settings/sync-conflicts` review route + `__APP_VERSION__`/`__APP_COMMIT__`/`__BUILD_TIME__` defines baked at build via Dockerfile `GIT_SHA` build-arg (host-side `git rev-parse --short HEAD` in `deploy-erosi.sh`) + "Acerca de" version chip in `/settings`; no migration; see `docs/history/fase-14-pwa-hardening.md`. **Fase 15: common items management** — migration 026 + pgTAP 018 + `item_frequency.weight integer` column, written only via admin-only SECURITY DEFINER RPCs (`set_item_frequency_weight` + `purge_item_frequency`) — existing all-deny client policies on `item_frequency` stay in place. Suggestion query reorders by `weight desc, use_count desc, last_used_at desc`. UI 3-way segmented control (Hide / Normal / Boost → -50 / 0 / 50) in `/collective/manage` (admin write, member read-only, guest hidden). `fetchSuggestions` gains `excludeNames` (capped at 200 names to bound URL length on PostgREST `not.in.()` filter) to drop items already on the active list from the dropdown; see `docs/history/fase-15-common-items.md`. **Final test totals (`just test-all`): 177 pgTAP + 179 Vitest integration + 47 Vitest unit + 93 Playwright + 1 gated rate-limit = 497 tests green; 3 skipped (2 Realtime presence — upstream `handle_out/3` bug `supabase/realtime#1617`; 1 rate-limit — gated). Delta vs MVP close: +132 pgTAP + +39 integration + +32 unit + +34 e2e = +237 tests across MVP2 fases 9–15.** Fase 7+8 already shipped as MVP cleanup, not MVP2.
|
||||||
|
|
||||||
**Pending in MVP2 (📋): Fase 15 — Common items management** (`plan/fase-15-common-items.md`). Extends `item_frequency` (migration 026) with a `weight integer` column written via admin-only SECURITY DEFINER RPCs (`set_item_frequency_weight` + `purge_item_frequency`). Suggestion query reorders by `weight desc, use_count desc, last_used_at desc`. UI 3-way segmented control (Hide / Normal / Boost → -50 / 0 / 50) lives in `/collective/manage` (admin write, member read-only, guest hidden). `fetchSuggestions` gains `excludeNames` arg to drop items already on the active list from the dropdown.
|
|
||||||
|
|
||||||
## Documentation Map
|
## Documentation Map
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,15 @@
|
|||||||
| Fase 6 — Deploy readiness | ✅ Completa (PWA generateSW + manifest + iconos placeholder + Kong rate-limit en invitaciones + rotación JWT dev + rotate-jwt.sh + `.env.erosi.example` + rls-audit.sh + `just lighthouse`). Rate-limit auth retirado — Keycloak brute-force nativa cubre el caso. Push notifications y iconos finales fuera de scope. |
|
| Fase 6 — Deploy readiness | ✅ Completa (PWA generateSW + manifest + iconos placeholder + Kong rate-limit en invitaciones + rotación JWT dev + rotate-jwt.sh + `.env.erosi.example` + rls-audit.sh + `just lighthouse`). Rate-limit auth retirado — Keycloak brute-force nativa cubre el caso. Push notifications y iconos finales fuera de scope. |
|
||||||
| Fase 7 — Collective-flow E2E tests | ✅ Completa (12 Playwright nuevos O-01..MC-05; 3 bugs latentes corregidos: RPC atómica `create_collective`, restore de `pendingInvitationToken` tras login, hidratación tardía de `$currentCollective` en manage; migración 013 trigger `role/aud` default). |
|
| Fase 7 — Collective-flow E2E tests | ✅ Completa (12 Playwright nuevos O-01..MC-05; 3 bugs latentes corregidos: RPC atómica `create_collective`, restore de `pendingInvitationToken` tras login, hidratación tardía de `$currentCollective` en manage; migración 013 trigger `role/aud` default). |
|
||||||
| Fase 8 — Prod auth hardening | ✅ Completa (migración 014 extiende `role/aud` guard a UPDATE; `logout()` RP-initiated Keycloak end-session + ruta pública `/logged-out`). |
|
| Fase 8 — Prod auth hardening | ✅ Completa (migración 014 extiende `role/aud` guard a UPDATE; `logout()` RP-initiated Keycloak end-session + ruta pública `/logged-out`). |
|
||||||
| **MVP2** — Fase 9 → 15 | 🔄 6/7 (fases 9–14 ✅ 2026-05-18; Fase 15 📋) |
|
| **MVP2** — Fase 9 → 15 | ✅ Completa (rama `mvp2`, 2026-05-18) |
|
||||||
| ↳ Fase 9 — Polish + Dark Mode | ✅ |
|
| ↳ Fase 9 — Polish + Dark Mode | ✅ |
|
||||||
| ↳ Fase 10 — Spec completion | ✅ |
|
| ↳ Fase 10 — Spec completion | ✅ |
|
||||||
| ↳ Fase 11 — Item tags + importance UX | ✅ |
|
| ↳ Fase 11 — Item tags + importance UX | ✅ |
|
||||||
| ↳ Fase 12 — Section visibility | ✅ |
|
| ↳ Fase 12 — Section visibility | ✅ |
|
||||||
| ↳ Fase 13 — Server administration | ✅ |
|
| ↳ Fase 13 — Server administration | ✅ |
|
||||||
| ↳ Fase 14 — PWA hardening | ✅ |
|
| ↳ Fase 14 — PWA hardening | ✅ |
|
||||||
| ↳ Fase 15 — Common items management | 📋 |
|
| ↳ Fase 15 — Common items management | ✅ |
|
||||||
| Suite de tests (pgTAP + Vitest + Playwright) | ✅ **476 tests verdes** (166 pgTAP + 173 integración + 47 unit + 89 E2E) + 1 rate-limit gated (`just test-rate-limit`). 3 skipped en `just test-all` (2 Realtime presence — upstream `handle_out/3` bug; 1 rate-limit — gated). |
|
| Suite de tests (pgTAP + Vitest + Playwright) | ✅ **497 tests verdes** (177 pgTAP + 179 integración + 47 unit + 93 E2E) + 1 rate-limit gated (`just test-rate-limit`). 3 skipped en `just test-all` (2 Realtime presence — upstream `handle_out/3` bug; 1 rate-limit — gated). |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user