History doc covers: ENUM-vs-CHECK rationale (plan was written against
the wrong primitive — actual gate is the language_code ENUM from
migration 001), machine-translation seed + [needs review] marker,
ICU-placeholder parity verification, locale-keys diff script
contract, and the ParaglideJS {#key lang}-on-navigation cross-cutting
gap that constrained the shape of EU-01.
Test deltas: pgTAP +5, integration +2, unit +4, e2e +2 — 581 + 3
skipped (was 568 + 3). Documents the pre-existing 010_sync_conflicts
flake (offline.test.ts e2e contamination) as out of scope for Fase 20.
CHANGELOG gains the [Unreleased] entry. Moves into [v1.0.0] in the
release commit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101 lines
11 KiB
Markdown
101 lines
11 KiB
Markdown
# Changelog
|
||
|
||
All notable changes are documented here. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Versions follow [Semantic Versioning](https://semver.org/).
|
||
|
||
Each bullet is prefixed with `[new]` (added capability), `[fix]` (resolved
|
||
defect) or `[tweak]` (behaviour or implementation change with no new
|
||
surface). Areas group related entries; section bullets ending in `:` are
|
||
labels for the area, not log entries.
|
||
|
||
## [Unreleased]
|
||
|
||
- [new] Required list title + auto-numbered prefix + admin-curated title catalog (Fase 18).
|
||
- [new] Emoji picker expanded with full food + animals categories (Fase 19).
|
||
- [new] Euskera (Basque) locale (Fase 20). Machine-translated seed pending native review.
|
||
|
||
## [v0.0.0-beta] — 2026-05-19 — MVP + MVP2 (Fases 0–16)
|
||
|
||
Single rollup for everything shipped before tagging started. Covers the
|
||
entire MVP cycle (Fases 0–7) plus the prod auth hardening pass (Fase 8)
|
||
and the eight MVP2 fases (9–16). Reads as a feature catalogue, not a
|
||
day-by-day diff — the per-fase docs in `docs/history/` and the per-fase
|
||
plans in `plan/` are the source of record.
|
||
|
||
- Auth + identity:
|
||
- [new] Keycloak → GoTrue → Supabase OIDC integration (PKCE), with `auth.users` pre-seed for the 5 dev users (Fase 1).
|
||
- [new] Self-registration via Keycloak; invitations are link-only (no email), generated on `/collective/manage` (Fase 1).
|
||
- [new] Multi-collective per user with sidebar switcher; active collective persisted to `localStorage` (Fase 1).
|
||
- [new] Atomic `create_collective(name, emoji)` RPC so onboarding works in a single round-trip without tripping `is_admin` / `is_member` policies (migration 012, Fase 7).
|
||
- [new] Public `/logged-out` route + RP-initiated Keycloak end-session on logout, so the SSO cookie is actually cleared and the next login re-prompts (Fase 8).
|
||
- [new] Account hard-delete (`delete_account()` RPC) with sole-admin auto-promote and a Danger-zone modal (migration 021, Fase 10.5).
|
||
- [fix] `auth.users.role`/`aud` default-fill trigger so PostgREST routing survives the Keycloak provisioning path; INSERT + UPDATE both covered to defeat GoTrue's pop-ORM re-clobber (migrations 013–014, Fases 7–8).
|
||
- [fix] `isLoggingOut` guard in `(app)/+layout.svelte` to suppress the auth-gate `$effect` during the logout navigation, closing a "PKCE code verifier not found in storage" race on prod (Fase 8).
|
||
- [fix] `pendingInvitationToken` restored from `sessionStorage` after login so the user lands on `/invitation/<token>` instead of `/onboarding` or `/lists` (Fase 7).
|
||
|
||
- Shopping lists + items:
|
||
- [new] Lists overview (featured + grid + completed + trash) and detail view with checkbox toggle, qty stepper, inline edit, drag-reorder (Fase 2a).
|
||
- [new] Frequency-driven suggestion chips on the add-item form, backed by the `item_frequency` table + trigger (Fase 2a; migration 006).
|
||
- [new] Realtime "Modo Compra" full-screen session view with 56 px toggles, flip animation, complete-list → redirect; postgres_changes subscription per list with echo-deduplication (Fase 2b; migration 007).
|
||
- [new] Offline-first sync queue (`SyncQueue` IDB-backed, FIFO flush, PK-conflict-as-success) with `online`-event auto-flush; offline/syncing banner mounted in detail + session views (Fase 2b).
|
||
- [new] Selection mode with bulk delete / move / mark-checked, long-press entry on mobile + desktop toggle button (Fase 5.11).
|
||
- [new] Reset-from-detail button on completed lists; "Crear nuevo colectivo" entry in sidebar + drawer (Fase 10).
|
||
- [new] Trash drawer restore + hard-delete via `restore_list()` / `hard_delete_list()` RPCs (migration 020, Fase 10.4).
|
||
- [new] Collective-scoped item tags (chips + picker + filter bar + realtime resort) backed by `item_tags` + `shopping_item_tags` (migration 022, Fase 11).
|
||
- [new] Common-items management on `/collective/manage` — 3-way Hide / Normal / Boost segmented control writing `weight` via admin-only RPCs; suggestion strip reorders by weight + use_count + last_used_at (migration 026, Fase 15).
|
||
- [new] Suggestion dropdown excludes names already on the active list (`excludeNames` capped at 200 to respect Kong URI limits) (Fase 15).
|
||
- [tweak] Item row redesigned to `drag-handle | name-button | qty stepper` with swipe-to-(un)check; double-tap opens an edit overlay; `unit` column dropped because it became unreachable (migration 011, Fase 5.10).
|
||
- [tweak] Add-form moved inline as the last child of the unchecked section; sticky bottom bars retired (Fase 5.14).
|
||
- [tweak] List rename inline at the top of the detail view with 500 ms debounced autosave; "New list" button moved to the masthead (Fase 5.8).
|
||
|
||
- Tasks + notes:
|
||
- [new] Task lists + tasks with completion-consistency CHECK (`is_completed ⇔ completed_by ⇔ completed_at`) and drag-reorder (migration 008, Fase 3).
|
||
- [new] Notes with 8-colour palette, pinned + archived (mutually exclusive), 7-day trash window enforced via RLS + `pg_cron` purge; editor with 500 ms debounced autosave (migration 009, Fase 3).
|
||
- [new] Sync-conflicts review route at `/settings/sync-conflicts`, paginated, side-by-side local vs remote payloads, per-device dismissal via `localStorage` (Fase 14.2).
|
||
|
||
- Search:
|
||
- [new] Cross-section search via `search_in_collective()` SECURITY INVOKER RPC over generated `tsvector` columns on items/tasks/notes; debounced input, filter chips, deep-link per result type (migration 010, Fase 4).
|
||
|
||
- Mobile UX + accessibility:
|
||
- [new] Mobile shell — top bar with hamburger + collective name + avatar, slide-in drawer, bottom tab bar with safe-area inset, sticky contextual headers on detail routes (Fase 5).
|
||
- [new] `UndoToast` for destructive actions (4 s TTL, auto-commit, mounted globally), with `scheduleUndoable()` queue (Fase 5).
|
||
- [new] Spinner component (`sm/md/lg`, `currentColor`, `motion-reduce:animate-none`, sr-only label) integrated at 7 loading sites (Fase 16).
|
||
- [tweak] Desktop reading width capped at `max-w-2xl` for content detail routes; mobile and `/lists/[id]/session` excluded (Fase 9.2).
|
||
|
||
- PWA + offline:
|
||
- [new] Installable PWA — Workbox precaching via `@vite-pwa/sveltekit`, manifest, iOS meta tags + apple-touch icons, placeholder slate-and-"C" icons (Fase 6.2).
|
||
- [new] Service-worker auto-registration via `useRegisterSW` + 15 min `reg.update` poll; `UpdateToast` with "Reload" action when a new build is available; "Ready to use offline" auto-dismiss toast (Fase 14.1).
|
||
- [new] `OfflineChip` in `MobileTopBar` + `DesktopSidebar` with a pending-ops badge when the queue is non-empty (Fase 14.2).
|
||
- [new] Build-time version constants (`__APP_VERSION__` / `__APP_COMMIT__` / `__BUILD_TIME__`) exposed via `$lib/version`; "Acerca de" chip on `/settings`; `GIT_SHA` baked through the Dockerfile build arg by the deploy script (Fase 14.3).
|
||
- [tweak] PWA strategy on prod switched to `generateSW` because `@vite-pwa/sveltekit` 0.6.8 hardcodes the source SW filename under `injectManifest` (Fase 6 → revisit in Fase 14).
|
||
- [fix] `<link rel="manifest">` added to `app.html` so Android Chrome surfaces the install prompt (Fase 14 follow-up).
|
||
|
||
- Collective management:
|
||
- [new] Rename collective + change emoji (CU-H07) on `/collective/manage` (Fase 10.2).
|
||
- [new] Leave-collective flow (CU-H06) with sole-admin auto-promote via `leave_collective()` RPC; sole-member rejected with P0001 (migration 017, Fase 10.1).
|
||
- [new] Dissolve-collective flow (CU-H08) with type-the-name confirmation, via `dissolve_collective()` RPC (migration 018, Fase 10.3).
|
||
- [new] Section visibility — per-user + per-collective `feature_flags jsonb` + `section_enabled()` STABLE SQL helper using COALESCE precedence (migration 023, Fase 12).
|
||
- [new] Auto-detect language on first sign-in from `navigator.languages`, gated to fresh accounts (`<60 s old` + `language = 'en'`) (Fase 10.6).
|
||
- [tweak] Every `created_by`/`updated_by` FK relaxed from `NOT NULL RESTRICT` to `NULL SET NULL` so a user delete cascades cleanly (migration 019, Fase 10.5).
|
||
|
||
- Server admin:
|
||
- [new] Global `server_admin` role (`server_admins` table) orthogonal to `collective_members`; `is_server_admin()` SECURITY DEFINER gate; bootstrap from `SERVER_ADMIN_EMAIL` on first DB init (migration 024, Fase 13).
|
||
- [new] `/admin` route group with 9 SECURITY DEFINER RPCs (collective lifecycle, member removal, server-level section defaults) + append-only `admin_actions` audit log + last-admin guard (migration 025, Fase 13).
|
||
- [new] `section_enabled()` extended with a server layer prepended to the user/collective precedence chain (Fase 13.2).
|
||
|
||
- i18n:
|
||
- [new] Paraglide JS messages for `en` + `es`, compiled at build time; `setLanguageTag()` flips the active locale without reload; selector on `/settings` writes to `public.users.language` (Fase 0).
|
||
- [new] Search + collective-management + PWA copy fully localised in both languages across every fase that added user-facing strings (Fases 4, 10, 14).
|
||
|
||
- Infra + deploy:
|
||
- [new] Local dev stack — Docker compose with Postgres / GoTrue / PostgREST / Realtime / Storage / Kong / Keycloak; `setup.sh` for idempotent first-time bring-up; `Justfile` task runner (Fase 0).
|
||
- [new] Production stack on ambrosio (OVH VPS) at https://erosi.limonia.net — `infra/scripts/deploy-erosi.sh` (rsync + first-deploy secret generation + every-deploy migration apply + pre-deploy backup + `.deploys.log` append) and `infra/scripts/rollback-erosi.sh` (paired code + DB rollback) (Fase 6 + later iterations).
|
||
- [new] Kong rate-limit on `/rest/v1/collective_invitations` (20/hour per Authorization header) with `request-transformer` URI rewrite (Fase 6.3).
|
||
- [new] JWT rotation script (`infra/scripts/rotate-jwt.sh`) + production env template + `rls-audit.sh` curl sweep + `just lighthouse` build-and-score recipe (Fase 6.4 + 6.5).
|
||
- [new] Internal Caddy on `:3000` fans `/rest|/auth|/realtime|/storage|/graphql|/pg` → Kong, everything else → app; external TLS terminator (off-stack) forwards plain HTTP to ambrosio:3000 (Fase 6 → revision after prod cutover).
|
||
- [new] Theme tokens stored as RGB triplets so `dark:` variants resolve consistently; three-mode preference (`light` / `dark` / `system`) persisted to `users.theme` + mirrored to `localStorage` with inline anti-FOUC script (migration 015, Fase 9.1).
|
||
- [new] `sync_conflicts` append-only log + queue-side divergence detection so last-write-wins conflicts are auditable (migration 016, Fase 9.3).
|
||
- [new] Pre-deploy `pg_dumpall` snapshot kept in `backups/predeploy-*.sql.gz` (newest 10) with paired code/DB rollback via `rollback-erosi.sh --previous` / `--to=<sha>` / `--code-only` (Fase 14 deploy work).
|
||
- [fix] `docker compose exec -T` calls inside SSH heredoc deploys now redirect stdin per call so the surrounding heredoc isn't drained — silently skipped migrations no longer happen (Fase 8 deploy hardening).
|
||
- [fix] PostgREST schema cache reload (`NOTIFY pgrst, 'reload schema'`) appended after every deploy and rollback so freshly-added RPCs are visible without a container restart (Fase 15 deploy work).
|
||
- [fix] WebKit Playwright project gated behind `RUN_WEBKIT=1` so hosts without the GTK libs (libicu74, libwoff1, …) keep `just test-all` green; `*.webkit.test.ts` files excluded from the chromium project (Fase 9.4).
|