xtablo-source/.planning/STATE.md
2026-05-18 16:04:22 +02:00

209 lines
16 KiB
Markdown
Raw Permalink 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.

---
gsd_state_version: 1.0
milestone: v4.0
milestone_name: Figma Design Parity
status: ready_to_plan
last_updated: 2026-05-18T14:04:17.721Z
last_activity: 2026-05-18 -- Phase 20 execution started
progress:
total_phases: 5
completed_phases: 2
total_plans: 9
completed_plans: 9
percent: 40
stopped_at: Phase 20 complete (3/3) — ready to discuss Phase 21
---
# STATE
**Project:** Xtablo Go+HTMX Product
**Milestone:** v3.0 — Design System & Visual Polish
**Created:** 2026-05-14
## Project Reference
See: `.planning/PROJECT.md` (updated 2026-05-17)
**Core value:** A user can sign in and run the Tablos workflow — organize work, attach files, discuss, and plan scheduled events — without a JS framework or managed chat provider.
**Current focus:** Phase 21 — task grid & roadmap views
## Current Position
Phase: 21
Plan: Not started
Status: Ready to plan
Last activity: 2026-05-18
## Previous Milestone Status
| # | Phase | Status |
|---|-------|--------|
| 8 | Social Sign-in | ✓ Complete |
| 9 | Etapes | ✓ Complete |
| 10 | Events | ✓ Complete |
| 11 | Individual Planning | ✓ Complete |
| 12 | Native Tablo Chat | ✓ Complete |
## Verification Record
- 2026-05-15: Phase 8 execution complete. Local verification passed with `go test ./... -count=1`; database-backed integration coverage skips unless `TEST_DATABASE_URL` is configured.
- 2026-05-15: Phase 9 UAT complete. Five browser checkpoints passed after fixing the selected-etape create gap; backend verification passed with `TEST_DATABASE_URL='postgres://xtablo:xtablo@localhost:5432/xtablo?sslmode=disable' go test ./... -count=1`.
- 2026-05-16: Phase 10 execution complete. Events UAT approved; backend verification passed with `TEST_DATABASE_URL='postgres://xtablo:xtablo@localhost:5432/xtablo?sslmode=disable' go test ./... -count=1`.
- 2026-05-16: Phase 12 execution complete. Discussion realtime UAT approved after duplicate-row and composer-reset fixes; backend verification passed with `just generate` and `TEST_DATABASE_URL='postgres://xtablo:xtablo@localhost:5432/xtablo?sslmode=disable' go test ./... -count=1`.
- 2026-05-16: Milestone v2.0 archived after acknowledging 7 legacy/open artifact items as deferred.
## Deferred Items
Items acknowledged and deferred at v3.0 milestone close on 2026-05-17 (all pre-existing from v1.0/v2.0):
| Category | Item | Status |
|----------|------|--------|
| uat_gap | Phase 05: 05-HUMAN-UAT.md | partial; 6 pending scenarios |
| uat_gap | Phase 07: 07-HUMAN-UAT.md | partial; 3 pending scenarios |
| verification_gap | Phase 03: 03-VERIFICATION.md | human_needed |
| verification_gap | Phase 04: 04-VERIFICATION.md | human_needed |
| verification_gap | Phase 05: 05-VERIFICATION.md | human_needed |
| verification_gap | Phase 07: 07-VERIFICATION.md | human_needed |
## Decisions
- **Consolidated internal/auth package** (not split with internal/session) — RESEARCH Open Question 3
- **compose Postgres + schema isolation for tests** (not testcontainers-go) — RESEARCH Open Question 1
- **goose.SetTableName per test-schema** prevents public goose_db_version table collision
- **argon2id** over bcrypt for password hashing — D-08, confirmed by user
- **Hand-rolled PHC encode/decode** (Pattern 1 verbatim) — no alexedwards/argon2id wrapper dep; keeps code lean and self-tested
- **Store.now injectable field** (not method/interface) — simpler for single-test-clock use case in MaybeExtend threshold tests
- **sha256.Sum256 inlined at Create + Lookup** (not in helper) — satisfies >= 2 grep acceptance criterion; makes D-05 hashing visible at usage sites
- **SignupForm/SignupErrors in templates package** (not handlers or separate forms pkg) — avoids import cycle between templates and internal/web
- **setupTestDB duplicated into web package test file** — Go prohibits importing _test.go files across packages; duplication chosen over non-test shared infra
- **nil-Store guard in auth.ResolveSession** — enables Phase 1 unit tests to pass AuthDeps{} zero value without panic
- **errInvalidCreds const** (not inline string) — satisfies D-20 single-source-of-truth grep gate; both credential failure paths use the constant
- **NewLimiterStoreWithClock exported** — cross-package integration tests inject a frozen clock without a test-helper shim
- **Status 401 for non-HTMX credential failures** — consistent with HTTP semantics; HTMX path returns 200+fragment
- **Layout takes *auth.User explicitly** (not thread-through-ctx) — easier to test templates in isolation; no magic context values
- **TestIndex_RendersHxGet rewritten to TestIndex_UnauthRedirects** — GET / is now protected; Phase 1 test was a false positive after this plan
- **csrf.PlaintextHTTPRequest(r) in dev mode** — skips TLS Referer check in plain-HTTP local dev/httptest; production unaffected
- **trustedOrigins variadic arg in auth.Mount + NewRouter** — test routers pass "localhost"; production passes none
- **sqlc-generated files not committed** — backend/.gitignore excludes internal/db/sqlc/*.go; just generate reproduces them (03-01)
- **NewRouter extended with TablosDeps parameter** — second explicit deps param before csrfKey; all call sites updated (03-01)
- **index_templ.go deleted manually after emptying index.templ** — templ generates broken import when .templ has no components (03-02)
- **Non-HTMX validation error re-fetches tablos and renders full dashboard** — no form state threading; simpler than threading form through full page (03-02)
- **_zone hidden field (title|desc) in edit fragments** — unified POST /tablos/{id} handler reads _zone to select which display fragment to return; misuse only affects response body, not DB state (03-03)
- **loadOwnedTablo helper for all parametric handlers** — uuid.Parse + GetTabloByID + ownership check factored into single function; 404 on any failure, 403 never used (D-04) (03-03)
- **TabloDeleteButtonFragment canonical delete-zone** — TabloCard delegates to it; single source of truth for zone HTML across card and detail-page contexts (03-03)
- **task_status ENUM order matches visual column order** (todo, in_progress, in_review, done) — ENUM ordinal sorting aligns with kanban column display order per Pitfall 6 (04-01)
- **Down migration drops TABLE before TYPE** — tasks table dropped before task_status type per Pitfall 3; type cannot be dropped while still referenced (04-01)
- **TasksDeps stub in test file** — declared in handlers_tasks_test.go; moved to handlers_tasks.go in Plan 02 to avoid file dependency before handlers exist (04-01)
- **TaskColumns/TaskColumnLabels in templates package** — moved from web package to templates to avoid web↔templates import cycle; handlers reference via templates.TaskColumns (04-02)
- **TabloDetailPage accepts tasks []sqlc.Task** — kanban board embedded below tablo header; TabloDetailHandler fetches tasks via ListTasksByTablo before rendering (04-02)
- **Dual reorder payload** — TaskReorderHandler supports array form (task_id[]/task_col[]) and single-value form (task_id/status/position) for test scaffold + Sortable.js compatibility (04-03)
- **GetTaskByID before UpdateTask in reorder** — preserves title+description (T-04-08), validates task-to-tablo ownership at fetch time (T-04-10) (04-03)
- **fileQuerier interface in OrphanCleanupWorker** — enables mock injection for pure unit tests without real DB; pool field retained for production (06-01)
- **river deps as // indirect until Plan 02** — cmd/worker wiring in Plan 02 will promote river to direct dependency; expected Go module behavior (06-01)
- **signal.NotifyContext after rivermigrate and S3 init** — startup I/O uses context.Background(); signal context created after all I/O succeeds; prevents river.Client.Start receiving a pre-cancelled context (RESEARCH Pitfall 2) (06-02)
- **pool.Close() explicit after StopAndCancel, not via defer** — StopAndCancel fully returns before pool is closed; matches PATTERNS.md pool close ordering (06-02)
- **Social-only users use NULL password_hash** — email/password login rejects them through the generic invalid-credentials path while provider sign-in owns the session path (08-01)
- **Verified provider identity links by provider subject first, then verified email** — prevents duplicate local users while keeping provider subject as the strongest identity key (08-02)
- **Apple callback uses GET/query response mode for the first working version** — keeps the callback inside existing CSRF middleware boundaries; Apple dashboard configuration must match (08-03)
- **Provider buttons degrade to disabled controls when config is missing** — auth pages remain deployable without provider credentials (08-04)
- **Account providers page is read-only in Phase 8** — linked identity visibility shipped before unlink/add-password account management (08-05)
- **Apple sign-in disabled after UAT scope change** — Apple controls are hidden, Apple auth routes are not mounted, and provider docs only cover Google for now (08-UAT)
- **Google button width: max-content (not 100%)** — matches Google Material Design branding guidelines; pill button naturally sized, not stretched to card width (14-02)
- **Roboto font loaded in auth_layout.templ only** — auth pages are the only gsi-material-button context; global stylesheet pollution avoided (14-02)
- **AuthProviderButtonsBlock/AuthProviderButtonControl removed** — superseded by GoogleButton from auth_components.templ; single-provider design, components consolidated (14-02)
- **Air dev .css watching added** — .css in include_ext + Tailwind in rebuild cmd; CSS edits now trigger reload without manual restart (14-02)
## Performance Metrics
| Phase | Plan | Duration | Tasks | Files |
|-------|------|----------|-------|-------|
| 02-authentication | 01 | ~10min | 3 | 9 |
| 02-authentication | 02 | ~8min | 2 | 4 |
| 02-authentication | 03 | ~15min | 2 | 5 |
| 02-authentication | 04 | ~25min | 2 | 11 |
| 02-authentication | 05 | ~7min | 2 | 9 |
| 02-authentication | 06 | ~12min | 1 | 9 |
| 02-authentication | 07 | ~25min | 1 | 18 |
| 03-tablos-crud | 01 | ~15min | 3 | 10 |
| 03-tablos-crud | 02 | ~4min | 3 | 8 |
| 03-tablos-crud | 03 | ~30min | 3 | 5 |
| 04-tasks-kanban | 01 | ~4min | 3 | 7 |
| 04-tasks-kanban | 02 | ~20min | 3 | 12 |
| Phase 04-tasks-kanban P03 | ~15min | 3 tasks | 3 files |
| 06-background-worker | 01 | ~15min | 2 | 9 |
| Phase 06-background-worker P01 | ~15min | 2 tasks | 9 files |
| 06-background-worker | 02 | ~10min | 2 | 3 |
| Phase 08 P01 | 25min | 2 tasks | 8 files |
| Phase 08 P02 | 35min | 2 tasks | 9 files |
| Phase 08 P03 | 30min | 2 tasks | 7 files |
| Phase 08 P04 | 20min | 2 tasks | 8 files |
| Phase 08 P05 | 20min | 2 tasks | 7 files |
| Phase 11 P01 | ~15min | 2 tasks | 15 files |
| Phase 11 P02 | ~20min | 2 tasks | 4 files |
| Phase 12 P01 | ~25min | 3 tasks | 22 files |
| Phase 12 P02 | ~25min | 2 tasks | 5 files |
| Phase 12 P03 | ~45min | 4 tasks | 9 files |
| Phase 14 P01 | 4min | 2 tasks | 5 files |
| Phase 14 P02 | ~30min | 2 tasks | 4 files |
| Phase 17-chat-planning P02 | 15min | 3 tasks | 6 files |
## Notes
- Existing `go-backend/` is set aside; new code lives in a fresh `backend/` Go package.
- DB schema is changing from the JS/Supabase version — user is in the loop on every schema decision (Phases 25).
- Phase 2 Plan 01 SUMMARY: `.planning/phases/02-authentication/02-01-SUMMARY.md`
- Phase 2 Plan 02 SUMMARY: `.planning/phases/02-authentication/02-02-SUMMARY.md`
- Phase 2 Plan 03 SUMMARY: `.planning/phases/02-authentication/02-03-SUMMARY.md`
- Commits (02-01): 513044d (migration), 799c260 (sqlc), 2c84f42 (auth package + test harness)
- Commits (02-02): 3bb3828 (RED tests), ee36a5c (GREEN implementation)
- Commits (02-03): fd2301d (session store + cookie helpers), 1d07830 (middleware)
- Commits (02-04): 73935ed (signup templates + smoke tests), efdc16b (handler + router + integration tests)
- Phase 2 Plan 04 SUMMARY: `.planning/phases/02-authentication/02-04-SUMMARY.md`
- Commits (02-05): b5c20c7 (LimiterStore + tests), 7d8c498 (login handler + integration tests)
- Phase 2 Plan 05 SUMMARY: `.planning/phases/02-authentication/02-05-SUMMARY.md`
- Commits (02-06): b5c3fc4 (RED tests), 8b54ff4 (logout + protected routes + layout)
- Phase 2 Plan 06 SUMMARY: `.planning/phases/02-authentication/02-06-SUMMARY.md`
- Commits (02-07): ae2d356 (RED tests), 389e1bc (GREEN csrf implementation)
- Phase 2 Plan 07 SUMMARY: `.planning/phases/02-authentication/02-07-SUMMARY.md`
- Phase 3 Plan 01 SUMMARY: `.planning/phases/03-tablos-crud/03-01-SUMMARY.md`
- Commits (03-01): f1b8d6e (migration + queries), c8f44b1 (TablosDeps stub + test scaffold), 2c1b186 (button CSS variants)
- Phase 3 Plan 02 SUMMARY: `.planning/phases/03-tablos-crud/03-02-SUMMARY.md`
- Commits (03-02): 43ddf25 (tablos templates + layout footer), 5db9215 (tablo handlers + router wiring), c08da7f (delete retired index.templ)
- 03-02 complete — all 3 tasks done including human-verify checkpoint approval
- Phase 3 Plan 03 SUMMARY: `.planning/phases/03-tablos-crud/03-03-SUMMARY.md`
- Commits (03-03): 6f167e2 (detail/edit/delete templates), ab6937c (handlers + router + all 10 TABLO tests green), b5fa318 (checkpoint approved)
- **Phase 3 complete** — All 3 plans done; TABLO-01..06 closed; 10/10 TABLO tests green; full browser verify passed 2026-05-15
- Phase 4 Plan 01 SUMMARY: `.planning/phases/04-tasks-kanban/04-01-SUMMARY.md`
- Commits (04-01): c9c8262 (migration + sqlc queries), 8b9543d (RED test scaffold + form structs), 55fb32f (Sortable.js + soft-danger CSS)
- Phase 4 Plan 02 SUMMARY: `.planning/phases/04-tasks-kanban/04-02-SUMMARY.md`
- Commits (04-02): 181ae79 (handlers + router + main.go), 889164b (templates + tablos.templ + layout.templ), 92ebb5f (activate task tests)
- Phase 4 Plan 03 SUMMARY: `.planning/phases/04-tasks-kanban/04-03-SUMMARY.md`
- Commits (04-03): 2b299e2 (TaskEditHandler + TaskUpdateHandler + TaskEditFragment + Sortable.js init), 5f87d7e (TaskReorderHandler + reorder test skips removed), f6deb87 (TestTaskOrderPersists active — full suite green)
- Phase 6 Plan 01 SUMMARY: `.planning/phases/06-background-worker/06-01-SUMMARY.md`
- Commits (06-01): 62e5e3e (river dep + ListOrphanFiles sqlc query), a1c2828 (internal/jobs package + unit tests)
- Phase 6 Plan 02 SUMMARY: `.planning/phases/06-background-worker/06-02-SUMMARY.md`
- Commits (06-02): 6e70478 (cmd/worker full river wiring), e202ad3 (just worker target + README docs)
- Phase 8 Plan 01 SUMMARY: `.planning/phases/08-social-sign-in/08-01-SUMMARY.md`
- Phase 8 Plan 02 SUMMARY: `.planning/phases/08-social-sign-in/08-02-SUMMARY.md`
- Phase 8 Plan 03 SUMMARY: `.planning/phases/08-social-sign-in/08-03-SUMMARY.md`
- Phase 8 Plan 04 SUMMARY: `.planning/phases/08-social-sign-in/08-04-SUMMARY.md`
- Phase 8 Plan 05 SUMMARY: `.planning/phases/08-social-sign-in/08-05-SUMMARY.md`
- Commits (08): 2d004cd (social identity schema foundation), 6779663 (Google sign-in), a8b6a03 (Apple implementation later disabled), 59fd6b1 (auth page provider controls), 6e65836 (account providers view + docs)
- Phase 9 Plan 01 SUMMARY: `.planning/phases/09-etapes/09-01-SUMMARY.md`
- Phase 9 Plan 02 SUMMARY: `.planning/phases/09-etapes/09-02-SUMMARY.md`
- Phase 9 Plan 03 SUMMARY: `.planning/phases/09-etapes/09-03-SUMMARY.md`
- Phase 9 Plan 04 SUMMARY: `.planning/phases/09-etapes/09-04-SUMMARY.md`
- Phase 9 UAT: `.planning/phases/09-etapes/09-UAT.md` — 5/5 checkpoints passed after selected-etape create fix.
- Commits (09): a8a3e5f/565bb88 (first etape slice), 9b89282/4af623a (management), 9f6c7eb/b22d79d (assignment selector), 55263e4/3a3ecf5/cf07c29 (reorder hardening), 0c95049/ee62ff9/f9fc7a1 (UAT fixes)
- Phase 14 Plan 01 SUMMARY: `.planning/phases/14-auth-pages/14-01-SUMMARY.md`
- Phase 14 Plan 02 SUMMARY: `.planning/phases/14-auth-pages/14-02-SUMMARY.md`
- Commits (14-01): cf116ff (logo assets + auth.css), e4d5f96 (auth_components.templ + auth_layout.templ)
- Commits (14-02): 808eaec (auth_login.templ), 65e3dbf (auth_signup.templ), 4624fb3 (Roboto + icon fix), 70fe384 (button width fix), 6e64cfb (air CSS watch)
---
*Last updated: 2026-05-16 after Phase 14 Plan 02 execution complete*
## Operator Next Steps
- Start the next milestone with /gsd-new-milestone