Commit graph

6 commits

Author SHA1 Message Date
Arthur Belleville
d15c3748e4
feat(12-03): add discussion SSE stream 2026-05-16 10:18:33 +02:00
Arthur Belleville
889164b437
feat(04-02): KanbanBoard, TaskCard, TaskDeleteConfirmFragment templates
- Add tasks.templ with KanbanBoard, KanbanColumn, TaskCard, TaskCreateFormFragment, TaskDeleteConfirmFragment, AddTaskTrigger, TaskCardOOB
- Add TaskColumns/TaskColumnLabels to tasks_forms.go (moved from web package to break import cycle)
- Update TabloDetailPage signature to accept tasks []sqlc.Task; embed KanbanBoard below tablo header
- Update handlers_tablos.go TabloDetailHandler to fetch tasks via ListTasksByTablo
- Update layout.templ: add sortable.min.js script tag, update footer to Phase 4 · Tasks
2026-05-15 09:32:06 +02:00
Arthur Belleville
43ddf25364
feat(03-02): tablos templates — dashboard, empty state, card, create form, OOB-clear
- Create backend/templates/tablos.templ with TablosDashboard, TablosEmptyState,
  TabloCard, TabloCreateFormFragment, TabloCardWithOOBFormClear components
- Create backend/templates/tablos_forms.go declaring TabloCreateForm and
  TabloCreateErrors types (mirrors auth_forms.go pattern)
- Update layout.templ footer: "Phase 2 · Authentication" → "Phase 3 · Tablos"
- TabloCardWithOOBFormClear emits OOB div as top-level sibling (Pitfall 5)
- TabloCard guards description/color rendering with pgtype.Text null checks
- All UI-SPEC copywriting copy strings present; templ generate succeeds
2026-05-15 00:17:56 +02:00
Arthur Belleville
389e1bc8b4
feat(02-07): gorilla/csrf integration — mount middleware, wire all forms, env-driven key
- auth.Mount(env, key) wraps csrf.Protect with locked D-14/D-24 options
- auth.LoadKeyFromEnv() reads SESSION_SECRET, hex-decodes, validates 32 bytes; fails fast on error
- ui.CSRFField(token) templ component renders hidden _csrf input
- Layout, LoginPage/Fragment, SignupPage/Fragment, Index all embed @ui.CSRFField(csrfToken)
- Handlers thread csrf.Token(r) into every page/fragment render call
- NewRouter mounts auth.Mount after ResolveSession, before all route groups (D-24)
- main.go calls auth.LoadKeyFromEnv(); logs.Fatalf on missing/invalid SESSION_SECRET
- SESSION_SECRET documented in .env.example with openssl rand -hex 32 instruction
- go.mod: gorilla/csrf v1.7.3 (direct); prior tests updated with getCSRFToken helper
- All Plan 04/05/06 tests updated to acquire and submit valid _csrf tokens
2026-05-14 22:59:06 +02:00
Arthur Belleville
8b54ff4bec
feat(02-06): implement logout, protect GET /, and update layout with auth state
- Add LogoutHandler: deletes session row (D-06), clears cookie, redirects to /login
- Protect GET / inside RequireAuth group; remove old top-level registration
- Add POST /logout inside same RequireAuth group (D-22: POST-only logout)
- Update Layout signature to accept *auth.User; render logout form + email when authed
- Update Index template to accept *auth.User and show "Signed in as {email}"
- Update SignupPage/LoginPage to pass nil to Layout (auth pages are unauthed)
- Update IndexHandler to pull user from auth.Authed(ctx) and pass to template
- Update TestIndex_RendersHxGet -> TestIndex_UnauthRedirects (GET / now protected)
- AUTH-04 (logout) and AUTH-05 (protected /) are now closed
2026-05-14 22:40:10 +02:00
Arthur Belleville
3a12f8f47d
feat(01-03): templ layout/index/fragments + handlers + chi router
- templates/layout.templ: base HTML shell per UI-SPEC §Base Layout Contract
  (max-w-5xl container, slate-50 header, slate-200 borders, footer copy,
  /static/tailwind.css in <head>, /static/htmx.min.js deferred at body end —
  D-10: HTMX never loaded from a CDN)
- templates/index.templ: root page consuming @ui.Card and @ui.Button for the
  canonical HTMX demo (UI-SPEC §Component Library Contract canonical block)
- templates/fragments.templ: TimeFragment renders <span> with RFC3339 UTC
  timestamp; templ auto-escapes interpolation (T-01-13)
- internal/web/handlers.go: HealthzHandler (200 ok / 503 degraded per D-20,
  2s Ping timeout), IndexHandler, DemoTimeHandler with injected clock
- internal/web/router.go: Pinger interface; NewRouter wires
  RequestIDMiddleware → RealIP → SlogLoggerMiddleware → Recoverer (D-08
  + Pitfall 6 — chi middleware.Logger deliberately NOT registered) and
  routes /, /healthz, /demo/time, /static/* via http.FileServer (T-01-08
  path traversal blocked by http.Dir)

All six handler tests + ui package tests are GREEN under default go test.
2026-05-14 19:25:43 +02:00