From c4406cf16cde7794f9994ed9507e9084d691b755 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Fri, 15 May 2026 00:22:16 +0200 Subject: [PATCH] =?UTF-8?q?docs(03-02):=20plan=2002=20SUMMARY=20+=20STATE?= =?UTF-8?q?=20update=20=E2=80=94=20checkpoint=20at=20Task=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 03-02-SUMMARY.md: TablosDeps, handler contracts, template contracts, 4/10 tests green, 6 RED for Plan 03, known stubs documented - STATE.md: 2 new decisions, plan 02 metrics row added, notes updated - ROADMAP.md: phase 3 progress updated (2/3 summaries) --- .planning/ROADMAP.md | 6 +- .planning/STATE.md | 14 +- .../phases/03-tablos-crud/03-02-SUMMARY.md | 175 ++++++++++++++++++ 3 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 .planning/phases/03-tablos-crud/03-02-SUMMARY.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 563486f..5bbfcc7 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -14,7 +14,7 @@ |---|-------|------|--------------| | 1 | Foundation | Fresh `backend/` Go package boots, renders HTMX, talks to Postgres | FOUND-01..05 | | 2 | Authentication | Complete (7/7) | AUTH-01..07 | -| 3 | 1/3 | In Progress| | +| 3 | 2/3 | In Progress| | | 4 | Tasks (Kanban) | A user can run a kanban board inside a tablo | TASK-01..07 | | 5 | Files | A user can attach, list, download, delete files on a tablo | FILE-01..06 | | 6 | Background Worker | A second binary runs jobs against the same Postgres | WORK-01..04 | @@ -82,10 +82,10 @@ Plans: **User-in-loop:** Approve the `tablos` table schema (ownership model, soft-delete vs hard-delete, slug strategy). -**Plans:** 1/3 plans executed +**Plans:** 2/3 plans executed Plans: - [x] 03-01-PLAN.md — Wave 0: migration 0003_tablos + sqlc queries + handlers_tablos_test.go RED scaffold + button.css danger/neutral variants -- [ ] 03-02-PLAN.md — Vertical slice 1: dashboard list + inline-form create (HTMX OOB swap; TABLO-01, TABLO-02, TABLO-06) +- [x] 03-02-PLAN.md — Vertical slice 1: dashboard list + inline-form create (HTMX OOB swap; TABLO-01, TABLO-02, TABLO-06) - [ ] 03-03-PLAN.md — Vertical slice 2: detail + inline edit (title/description) + inline-confirmation delete (TABLO-03, TABLO-04, TABLO-05, TABLO-06) ### Phase 4: Tasks (Kanban) diff --git a/.planning/STATE.md b/.planning/STATE.md index c62196c..926f3b7 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,13 +3,13 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: in_progress -last_updated: "2026-05-14T22:15:00.679Z" +last_updated: "2026-05-14T22:21:35.039Z" progress: total_phases: 7 completed_phases: 2 total_plans: 14 - completed_plans: 12 - percent: 86 + completed_plans: 13 + percent: 93 --- # STATE @@ -68,6 +68,8 @@ See: `.planning/PROJECT.md` (updated 2026-05-14) - **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) ## Performance Metrics @@ -81,6 +83,7 @@ See: `.planning/PROJECT.md` (updated 2026-05-14) | 02-authentication | 06 | ~12min | 1 | 9 | | 02-authentication | 07 | ~25min | 1 | 18 | | 03-tablos-crud | 01 | ~15min | 3 | 10 | +| 03-tablos-crud | 02 | ~4min | 2 | 7 | ## Notes @@ -102,6 +105,9 @@ See: `.planning/PROJECT.md` (updated 2026-05-14) - 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) +- 03-02 stopped at Task 3 checkpoint:human-verify --- -*Last updated: 2026-05-14 after Phase 3 Plan 01 completion* +*Last updated: 2026-05-14 after Phase 3 Plan 02 Tasks 1+2 (checkpoint at Task 3)* diff --git a/.planning/phases/03-tablos-crud/03-02-SUMMARY.md b/.planning/phases/03-tablos-crud/03-02-SUMMARY.md new file mode 100644 index 0000000..cdcf57e --- /dev/null +++ b/.planning/phases/03-tablos-crud/03-02-SUMMARY.md @@ -0,0 +1,175 @@ +--- +phase: 03-tablos-crud +plan: 02 +subsystem: web-handlers + templates +tags: [go, htmx, templ, chi, csrf, tablo-crud] + +# Dependency graph +requires: + - phase: 03-tablos-crud + plan: 01 + provides: tablos table migration, sqlc queries, TablosDeps stub, RED test scaffold, button CSS variants +provides: + - TablosDashboard template (full page): heading, New-tablo button, create-form slot, card list + - TablosEmptyState template: "No tablos yet" + CTA with exact UI-SPEC copy + - TabloCard template: title, optional description/color dot, View link, .tablo-delete-zone wrapper + - TabloCreateFormFragment template: inline HTMX form with CSRF, field errors, Cancel link + - TabloCardWithOOBFormClear template: card + top-level OOB div clearing #create-form-slot + - TabloCreateForm + TabloCreateErrors form types (tablos_forms.go) + - TablosListHandler — GET / lists user tablos newest-first + - TablosNewHandler — GET /tablos/new returns create form fragment + - TablosCreateHandler — POST /tablos validates, inserts, dual-target HTMX swap or 303 redirect + - router.go: GET / → TablosListHandler, GET /tablos/new, POST /tablos registered + - layout.templ footer updated: "Phase 3 · Tablos" + - TestTabloList, TestTabloList_Empty, TestTabloCreate, TestTabloCreate_Validation: GREEN (4/10) +affects: [03-03] + +# Tech tracking +tech-stack: + added: [] + patterns: + - Dual-target HTMX swap: HX-Retarget + hx-swap-oob sibling in single response (Pattern 4) + - OOB div as top-level sibling in templ component (Pitfall 5 handled) + - r.PostFormValue only — gorilla/csrf body consumption guard (Pitfall 2) + - pgtype.Text{String: s, Valid: s != ""} for nullable insert params + - renderTabloCreateError helper mirrors renderSignupError pattern + +key-files: + created: + - backend/templates/tablos.templ + - backend/templates/tablos_forms.go + modified: + - backend/internal/web/handlers_tablos.go + - backend/internal/web/handlers.go + - backend/internal/web/router.go + - backend/templates/layout.templ + - backend/templates/index.templ + +key-decisions: + - "index_templ.go deleted manually — templ generates broken import when .templ has no components" + - "IndexHandler removed from handlers.go; auth/csrf imports removed (now unused)" + - "index.templ reduced to bare package declaration rather than deleted — keeps file discoverable" + - "Non-HTMX validation error re-fetches tablos and renders full dashboard (no form state threading)" + +patterns-established: + - "Pattern: TabloCardWithOOBFormClear emits OOB div as top-level sibling (Pitfall 5)" + - "Pattern: dual-target HTMX create swap via HX-Retarget + HX-Reswap headers" + - "Pattern: nullable pgtype.Text insert via Valid: s != '' guard" + +requirements-completed: + - TABLO-01 + - TABLO-02 + - TABLO-06 + +# Metrics +duration: ~4min +completed: 2026-05-14 +--- + +# Phase 03 Plan 02: Tablos Dashboard + Create Slice Summary + +**tablos.templ dashboard/card/form components + TablosListHandler/NewHandler/CreateHandler wiring 4/10 integration tests green; HTMX dual-target create and non-HTMX 303 fallback both verified** + +## Performance + +- **Duration:** ~4 min +- **Started:** 2026-05-14T22:16:47Z +- **Completed:** 2026-05-14T22:20:30Z (pre-checkpoint — Tasks 1+2 only) +- **Tasks:** 2 of 3 (Task 3 is human-verify checkpoint) +- **Files modified:** 7 + +## Accomplishments + +- `tablos.templ` created with 5 components: TablosDashboard, TablosEmptyState, TabloCard, TabloCreateFormFragment, TabloCardWithOOBFormClear +- `tablos_forms.go` with TabloCreateForm + TabloCreateErrors types (mirrors auth_forms.go) +- `layout.templ` footer updated from "Phase 2 · Authentication" to "Phase 3 · Tablos" +- `handlers_tablos.go` filled from stub to full implementation (List/New/Create handlers) +- `router.go` protected group updated: GET / → TablosListHandler, + GET /tablos/new, POST /tablos +- `handlers.go` IndexHandler removed; `index.templ` emptied; `index_templ.go` deleted +- TestTabloList, TestTabloList_Empty, TestTabloCreate (HTMX + non-HTMX), TestTabloCreate_Validation all PASS +- Phase 1/2 tests (TestSignup/TestLogin/TestLogout/TestCSRF) still pass — no regression + +## Task Commits + +1. **Task 1: tablos templates + layout footer** - `43ddf25` (feat) +2. **Task 2: tablo handlers + router wiring** - `5db9215` (feat) + +## Tests: 4 of 10 Green, 6 Remain RED for Plan 03 + +| Test | Status | +|------|--------| +| TestTabloList | GREEN | +| TestTabloList_Empty | GREEN | +| TestTabloCreate/HTMX_create | GREEN | +| TestTabloCreate/non-HTMX_create | GREEN | +| TestTabloCreate_Validation | GREEN | +| TestTabloDetail_Owner | RED (Plan 03) | +| TestTabloDetail_NonOwner | RED (Plan 03) | +| TestTabloDetail_InvalidID | RED (Plan 03) | +| TestTabloUpdate | RED (Plan 03) | +| TestTabloDeleteConfirm | RED (Plan 03) | +| TestTabloDelete/HTMX_delete | RED (Plan 03) | +| TestTabloDelete/non-HTMX_delete | RED (Plan 03) | + +## Handler Contracts Established + +**TablosDeps** (unchanged from Plan 01): +```go +type TablosDeps struct { + Queries *sqlc.Queries +} +``` + +**Handler signatures:** +- `TablosListHandler(deps TablosDeps) http.HandlerFunc` — GET / +- `TablosNewHandler(deps TablosDeps) http.HandlerFunc` — GET /tablos/new +- `TablosCreateHandler(deps TablosDeps) http.HandlerFunc` — POST /tablos + +**NewRouter signature** (unchanged from Plan 01): +```go +func NewRouter(pinger Pinger, staticDir string, deps AuthDeps, tabloDeps TablosDeps, csrfKey []byte, env string, trustedOrigins ...string) http.Handler +``` + +## Template Contracts for Plan 03 + +- `TabloCard` wraps Delete button in `
` — Plan 03 wires /delete-confirm to swap outerHTML +- `TabloCard` renders "View" link to `/tablos/{id}` — Plan 03 implements that route +- All 5 template components in `tablos.templ` are callable by Plan 03 + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Deleted stale index_templ.go after emptying index.templ** +- **Found during:** Task 2 (after reducing index.templ to bare package declaration) +- **Issue:** `templ generate` regenerated index_templ.go with `import "github.com/a-h/templ"` even though the file has no templ components, causing `go build` to fail with "imported and not used". +- **Fix:** Deleted `backend/templates/index_templ.go` manually after `just generate`; build passes. +- **Files modified:** backend/templates/index_templ.go (deleted) +- **Committed in:** 5db9215 (Task 2) + +## Known Stubs + +- `TabloCard` Delete button fires `hx-get="/tablos/{id}/delete-confirm"` — the `/delete-confirm` route does not exist yet (Plan 03 implements it). The button is visible on the dashboard but clicking it returns a 404 until Plan 03. +- `TabloCard` "View" link points to `/tablos/{id}` — route not yet registered (Plan 03). Navigating returns chi's default 404 until Plan 03. + +These stubs are intentional per plan design — Plan 02 establishes the zone and link shapes that Plan 03 will wire. + +## Checkpoint Status + +Task 3 (human-verify) reached — execution paused awaiting manual browser verification of: +1. Dashboard "Your Tablos" heading + tablo cards or empty state +2. "New tablo" button HTMX fetch of inline form +3. HTMX create: form clears, card prepends, no full reload +4. Validation: empty title shows "Title is required." inline +5. Non-JS POST → 303 redirect to /, tablo in list +6. CSRF token present in form `_csrf` hidden field + +## Next Phase Readiness + +- Plan 03 can implement TabloDetail, TabloUpdate, TabloDeleteConfirm, TabloDelete, and TabloDeleteCancel handlers and routes. +- TablosDeps available, NewRouter signature stable. +- `.tablo-delete-zone` class on TabloCard wired for Plan 03's delete-confirm OOB swap. + +--- +*Phase: 03-tablos-crud* +*Completed (partial — checkpoint): 2026-05-14*