docs(04-02): complete kanban vertical slice plan — handlers, templates, test activation

- Add 04-02-SUMMARY.md with full decisions and deviation documentation
- Update STATE.md: Plans 01-02 done, add decisions, metrics, notes
- Update ROADMAP.md phase 4 progress (2/4 plans complete)
This commit is contained in:
Arthur Belleville 2026-05-15 09:35:03 +02:00
parent 92ebb5f5fe
commit 5158eb09af
No known key found for this signature in database
3 changed files with 135 additions and 9 deletions

View file

@ -15,7 +15,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 | Tablos CRUD | Complete (3/3) | TABLO-01..06 |
| 4 | 1/4 | In Progress| |
| 4 | 2/4 | In Progress| |
| 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 |
| 7 | Deploy v1 | The product runs in production on a single host | DEPLOY-01..05 |
@ -103,10 +103,10 @@ Plans:
**User-in-loop:** Approve the `task_columns` (or fixed-column) schema and the ordering strategy (fractional indices, gaps-of-100, linked list — to be decided with research). Approve whether reorder is drag-and-drop or button-driven.
**Plans:** 1/4 plans executed
**Plans:** 2/4 plans executed
Plans:
- [x] 04-01-PLAN.md — Wave 0: migration 0004_tasks + sqlc queries + handlers_tasks_test.go RED scaffold + soft-danger button CSS + Sortable.js bootstrap
- [ ] 04-02-PLAN.md — Vertical slice 1: kanban board render + task create + task delete (TASK-01, TASK-02, TASK-06)
- [x] 04-02-PLAN.md — Vertical slice 1: kanban board render + task create + task delete (TASK-01, TASK-02, TASK-06)
- [ ] 04-03-PLAN.md — Vertical slice 2: task inline edit + Sortable.js drag reorder/move (TASK-03, TASK-04, TASK-05, TASK-07)
- [ ] 04-04-PLAN.md — Human-verify checkpoint: full kanban board browser verification

View file

@ -3,13 +3,13 @@ gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: ready_to_execute
last_updated: "2026-05-15T07:25:45.316Z"
last_updated: "2026-05-15T07:34:10.554Z"
progress:
total_phases: 7
completed_phases: 3
total_plans: 18
completed_plans: 15
percent: 83
completed_plans: 16
percent: 89
---
# STATE
@ -32,14 +32,14 @@ See: `.planning/PROJECT.md` (updated 2026-05-14)
| 1 | Foundation | ✓ Complete |
| 2 | Authentication | ✓ Complete — VERIFIED PASS (2026-05-14) |
| 3 | Tablos CRUD | ✓ Complete — All 3 plans done, TABLO-01..06 closed, verified 2026-05-15 |
| 4 | Tasks (Kanban) | ◷ In Progress — Plan 01 done |
| 4 | Tasks (Kanban) | ◷ In Progress — Plans 01-02 done |
| 5 | Files | ○ Pending |
| 6 | Background Worker | ○ Pending |
| 7 | Deploy v1 | ○ Pending |
## Active Phase
**Phase 4: Tasks (Kanban)** — In progress. Plan 01 done (Wave 0 foundation). Plans 02-04 pending.
**Phase 4: Tasks (Kanban)** — In progress. Plans 01-02 done (Wave 0 foundation + Wave 1 vertical slice). Plans 03-04 pending.
## Verification Record
@ -76,6 +76,8 @@ See: `.planning/PROJECT.md` (updated 2026-05-14)
- **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)
## Performance Metrics
@ -92,6 +94,7 @@ See: `.planning/PROJECT.md` (updated 2026-05-14)
| 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 |
## Notes
@ -121,6 +124,8 @@ See: `.planning/PROJECT.md` (updated 2026-05-14)
- **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)
---
*Last updated: 2026-05-15 after Phase 4 Plan 01 complete (Wave 0 foundation)*
*Last updated: 2026-05-15 after Phase 4 Plan 02 complete (Wave 1 vertical slice — kanban board + create + delete)*

View file

@ -0,0 +1,121 @@
---
phase: 04-tasks-kanban
plan: "02"
subsystem: backend/tasks
tags: [kanban, htmx, handlers, templ, tdd-green]
dependency_graph:
requires: [04-tasks-kanban/04-01]
provides: [kanban-board-ui, task-create, task-delete, task-handlers, task-routes]
affects: [backend/internal/web, backend/templates, backend/cmd/web]
tech_stack:
added: []
patterns: [htmx-oob-swap, chi-route-ordering, templ-components, ownership-guard]
key_files:
created:
- backend/internal/web/handlers_tasks.go
- backend/templates/tasks.templ
modified:
- backend/internal/web/router.go
- backend/cmd/web/main.go
- backend/templates/tablos.templ
- backend/templates/layout.templ
- backend/templates/tasks_forms.go
- backend/internal/web/handlers_tablos.go
- backend/internal/web/handlers_tasks_test.go
- backend/internal/web/handlers_test.go
- backend/internal/web/handlers_tablos_test.go
- backend/internal/web/handlers_auth_test.go
- backend/internal/web/csrf_test.go
decisions:
- "TaskColumns/TaskColumnLabels moved to templates package to avoid web↔templates import cycle"
- "TabloDetailPage updated to accept tasks []sqlc.Task; handlers_tablos.go fetches tasks via ListTasksByTablo before rendering"
- "Non-HTMX validation error in TabloUpdateHandler also fetches tasks for kanban board rendering"
- "AddTaskTrigger and TaskCard use raw CSS class string for soft-danger button (not ui.Button) per plan spec"
- "Column labels match tasks_forms.go TaskColumnLabels; test scaffold updated from incorrect capitalization"
metrics:
duration: ~20min
completed: "2026-05-15"
tasks: 3
files: 12
---
# Phase 4 Plan 02: Kanban Board Vertical Slice (Wave 1) Summary
Vertical slice 1 of the kanban workflow: renders the kanban board on tablo detail page with 4 columns, implements task creation via inline column form with HTMX, and task deletion with inline confirmation. Users can now open a tablo, see 4 columns (To do, In progress, In review, Done), create tasks, and delete them.
## Tasks Completed
| Task | Name | Commit | Files |
|------|------|--------|-------|
| 1 | handlers_tasks.go + router + main.go | 181ae79 | backend/internal/web/handlers_tasks.go, router.go, main.go, 5 test files |
| 2 | tasks.templ + tablos.templ + layout.templ | 889164b | backend/templates/tasks.templ, tablos.templ, layout.templ, tasks_forms.go, handlers_tablos.go |
| 3 | Activate task integration tests | 92ebb5f | backend/internal/web/handlers_tasks_test.go |
## Verification Results
- `go build ./...` exits 0
- `go test ./...` exits 0 (all tests pass or skip correctly)
- `go test ./internal/web/ -run TestTask -v`: 9 SKIP total — 5 skip due to no TEST_DATABASE_URL (activated, awaiting DB), 4 skip with "handlers_tasks not yet implemented" (Plan 03)
- `grep -c 'KanbanBoard' templates/tasks.templ` returns 2
- `grep -c 'TaskCreateHandler' internal/web/router.go` returns 1
- `grep -c 'sortable.min.js' templates/layout.templ` returns 1
## Decisions Made
1. **TaskColumns/TaskColumnLabels moved to templates package**`handlers_tasks.go` imports `templates`, and `tasks.templ` needs the column definitions. Putting them in `web` package would create a cycle (`templates` → `web` → ... → `templates`). Moving to `templates/tasks_forms.go` breaks the cycle cleanly.
2. **TabloDetailPage signature updated** — Added `tasks []sqlc.Task` parameter. All callers updated: `TabloDetailHandler` fetches tasks via `ListTasksByTablo`; `TabloUpdateHandler` non-HTMX error path also fetches tasks for correct rendering.
3. **Task column header strings corrected** — The Plan 01 test scaffold used `"Todo"`, `"In Progress"`, `"In Review"` which didn't match the plan spec `"To do"`, `"In progress"`, `"In review"`. Updated test to use correct labels from `TaskColumnLabels`.
4. **Integration tests skip on missing TEST_DATABASE_URL** — Tests are activated (no t.Skip), but the test helper `setupTestDB` skips when no database is configured. This is the correct behavior per the existing test pattern.
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 2 - Import cycle prevention] TaskColumns/TaskColumnLabels moved from web to templates package**
- **Found during:** Task 2 (templ generation, go build cycle check)
- **Issue:** `tasks.templ` needs `web.TaskColumns` and `web.TaskColumnLabels`. But `templates` package imports `web/ui` (not `web`), and `web` imports `templates` — adding `web` as a direct import to `templates` would create `web → templates → web` cycle.
- **Fix:** Moved `TaskColumns` and `TaskColumnLabels` to `backend/templates/tasks_forms.go`. Handlers reference `templates.TaskColumns` via the already-existing `templates` import. No structural change — just a different home for the constants.
- **Files modified:** backend/templates/tasks_forms.go, backend/internal/web/handlers_tasks.go
- **Commit:** 181ae79
**2. [Rule 1 - Bug] Column header test strings corrected**
- **Found during:** Task 3 (activating tests)
- **Issue:** Plan 01 scaffold used `"Todo"`, `"In Progress"`, `"In Review"` but TaskColumnLabels defines `"To do"`, `"In progress"`, `"In review"`.
- **Fix:** Updated `TestTasksKanbanRenders` to use the correct label strings.
- **Files modified:** backend/internal/web/handlers_tasks_test.go
- **Commit:** 92ebb5f
**3. [Rule 3 - Router update] All NewRouter call sites updated**
- **Found during:** Task 1 (adding TasksDeps param to NewRouter)
- **Issue:** 5 test helper functions across 4 test files called `NewRouter` without `TasksDeps`.
- **Fix:** Updated all callers: `handlers_test.go`, `handlers_tablos_test.go`, `handlers_auth_test.go`, `csrf_test.go`.
- **Files modified:** 4 test files
- **Commit:** 181ae79
## Known Stubs
- `TaskEditHandler` returns 501 — Plan 03 implements task editing
- `TaskUpdateHandler` returns 501 — Plan 03 implements task update
- `TaskReorderHandler` returns 501 — Plan 03 implements drag-and-drop reorder
These stubs are intentional per the plan spec; routes are registered so route resolution tests work.
## Threat Flags
None — all threat mitigations from the plan's threat register are implemented:
- T-04-03: loadOwnedTabloForTask uses `GetTaskByID(WHERE id=$1 AND tablo_id=$2)` with ownership-verified tablo_id
- T-04-04: title validated non-empty, max 255 chars
- T-04-05: status validated against validTaskStatuses map before DB insert
- T-04-07: TabloDetailPage only renders after loadOwnedTablo passes ownership check
## Self-Check: PASSED
- backend/internal/web/handlers_tasks.go: FOUND
- backend/templates/tasks.templ: FOUND
- backend/internal/web/router.go (TaskCreateHandler): FOUND
- backend/templates/layout.templ (sortable.min.js): FOUND
- backend/templates/tablos.templ (tasks param): FOUND
- Commits 181ae79, 889164b, 92ebb5f: FOUND