From f848c42e54d03cf57db77592eb35afc58e9b7c38 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Sat, 16 May 2026 10:04:06 +0200 Subject: [PATCH] docs(12): create phase plan --- .planning/STATE.md | 22 +- .../phases/12-native-tablo-chat/12-01-PLAN.md | 170 +++++++++++++++ .../phases/12-native-tablo-chat/12-02-PLAN.md | 129 ++++++++++++ .../phases/12-native-tablo-chat/12-03-PLAN.md | 197 ++++++++++++++++++ .../12-native-tablo-chat/12-PATTERNS.md | 53 +++++ .../12-native-tablo-chat/12-RESEARCH.md | 165 +++++++++++++++ .../12-native-tablo-chat/12-VALIDATION.md | 67 ++++++ 7 files changed, 792 insertions(+), 11 deletions(-) create mode 100644 .planning/phases/12-native-tablo-chat/12-01-PLAN.md create mode 100644 .planning/phases/12-native-tablo-chat/12-02-PLAN.md create mode 100644 .planning/phases/12-native-tablo-chat/12-03-PLAN.md create mode 100644 .planning/phases/12-native-tablo-chat/12-PATTERNS.md create mode 100644 .planning/phases/12-native-tablo-chat/12-RESEARCH.md create mode 100644 .planning/phases/12-native-tablo-chat/12-VALIDATION.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 9afa524..5504b63 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v2.0 milestone_name: Collaboration, planning, and social sign-in -status: planning -last_updated: "2026-05-16T07:55:44.531Z" -last_activity: 2026-05-16 +status: executing +last_updated: "2026-05-16T08:03:11.927Z" +last_activity: 2026-05-16 -- Phase 12 planning complete progress: total_phases: 5 completed_phases: 4 - total_plans: 15 + total_plans: 18 completed_plans: 15 - percent: 100 + percent: 83 --- # STATE @@ -24,15 +24,15 @@ progress: See: `.planning/PROJECT.md` (updated 2026-05-15) **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 11 — Individual Planning +**Current focus:** Phase 12 — Native Tablo Chat ## Current Position Phase: 12 Plan: Not started -Status: Ready to plan -Last activity: 2026-05-16 -Resume file: .planning/phases/12-native-tablo-chat/12-UI-SPEC.md +Status: Ready to execute +Last activity: 2026-05-16 -- Phase 12 planning complete +Resume file: .planning/phases/12-native-tablo-chat/12-01-PLAN.md ## Phase Status @@ -41,8 +41,8 @@ Resume file: .planning/phases/12-native-tablo-chat/12-UI-SPEC.md | 8 | Social Sign-in | ✓ Complete | | 9 | Etapes | ◆ UAT passed; security pending | | 10 | Events | ✓ Complete | -| 11 | Individual Planning | ◆ Ready to execute | -| 12 | Native Tablo Chat | ○ Pending | +| 11 | Individual Planning | ✓ Complete | +| 12 | Native Tablo Chat | ◆ Ready to execute | ## Verification Record diff --git a/.planning/phases/12-native-tablo-chat/12-01-PLAN.md b/.planning/phases/12-native-tablo-chat/12-01-PLAN.md new file mode 100644 index 0000000..c4087f1 --- /dev/null +++ b/.planning/phases/12-native-tablo-chat/12-01-PLAN.md @@ -0,0 +1,170 @@ +--- +phase: 12-native-tablo-chat +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - backend/migrations/0009_discussion.sql + - backend/internal/db/queries/discussion.sql + - backend/internal/web/handlers_discussion_test.go + - backend/internal/web/handlers_discussion.go + - backend/internal/web/router.go + - backend/cmd/web/main.go + - backend/templates/tablos.templ + - backend/templates/discussion.templ + - backend/templates/discussion_forms.go +autonomous: true +requirements: [CHAT-01, CHAT-02, CHAT-03, CHAT-06] + +must_haves: + truths: + - "D-01/D-02/D-03/D-04: Discussion is a fifth tablo detail tab after Events, with direct full-page fallback." + - "D-06/D-07/D-08/D-09/D-10: rows show author, absolute timestamp, text, oldest first, day separators, bottom composer, and specified empty state." + - "D-11/D-12/D-13/D-14: schema carries nullable edit/delete metadata; no edit/delete UI appears." + - "D-15/D-16: composer is textarea plus Send message; no Enter-to-send behavior." + - "D-22/D-23/D-24/D-25: owner-only; author label uses email fallback; header may show 1 participant." + - "CHAT-06: message body is length-limited server-side and rendered escaped through templ." + artifacts: + - path: "backend/migrations/0009_discussion.sql" + provides: "message and read-state schema foundation" + - path: "backend/internal/db/queries/discussion.sql" + provides: "typed sqlc discussion history/send/read queries" + - path: "backend/internal/web/handlers_discussion.go" + provides: "protected discussion tab and send handlers" + - path: "backend/templates/discussion.templ" + provides: "server-rendered discussion UI" +--- + + +Vertical slice 1: add persisted discussion history and CSRF-protected message posting inside the tablo detail Discussion tab, without realtime or dashboard unread badges yet. + + + +@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/12-native-tablo-chat/12-CONTEXT.md +@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/12-native-tablo-chat/12-UI-SPEC.md +@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/12-native-tablo-chat/12-RESEARCH.md +@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/12-native-tablo-chat/12-PATTERNS.md + + + +T-12-01 Schema bypass: message rows must reference real tablos/users with cascading foreign keys. +T-12-02 Future lifecycle ambiguity: include nullable edit/delete metadata but do not expose edit/delete UI or decide tombstone copy. +T-12-03 Unauthenticated access: discussion routes must live inside `auth.RequireAuth`. +T-12-04 Cross-user leak/mutation: all handlers must call `loadOwnedTablo`; non-owner access returns 404. +T-12-05 XSS/body abuse: body is trimmed, non-empty, max-length checked, and rendered through templ escaped expressions. +T-12-06 CSRF bypass: message send remains normal POST with gorilla/csrf hidden token. + + + + + + Task 1: Add discussion schema and sqlc queries + + - backend/migrations/0009_discussion.sql + - backend/internal/db/queries/discussion.sql + + + - backend/migrations/0003_tablos.sql + - backend/migrations/0008_events.sql + - backend/internal/db/queries/tablos.sql + - backend/internal/db/queries/events.sql + - .planning/phases/12-native-tablo-chat/12-RESEARCH.md + + + Create `discussion_messages` with `id uuid default gen_random_uuid()`, `tablo_id uuid not null references tablos(id) on delete cascade`, `author_user_id uuid not null references users(id) on delete restrict`, `body text not null`, `created_at timestamptz not null default now()`, `updated_at timestamptz not null default now()`, nullable `edited_at`, `edited_by_user_id`, `deleted_at`, and `deleted_by_user_id`. Add checks for non-blank trimmed body and maximum body length; use 10000 characters unless implementation finds a stronger local convention. + Create `discussion_read_states` keyed by `(tablo_id, user_id)` with nullable `last_read_message_id`, `last_read_at timestamptz not null default now()`, `created_at`, and `updated_at`. + Add indexes for `(tablo_id, created_at, id)` and read-state lookup. Add sqlc queries for list history oldest-first with author email, insert message, get message row with author email, and upsert read state. + + + cd backend && just generate + + + - Migration includes message lifecycle metadata fields required by CHAT-03. + - Migration includes persistent read-state table for later D-05/D-26 work. + - `discussion.sql` exposes typed queries needed by history and send handlers. + - `cd backend && just generate` exits 0. + + + + + Task 2: Add RED discussion handler tests + + - backend/internal/web/handlers_discussion_test.go + + + - backend/internal/web/handlers_events_test.go + - backend/internal/web/handlers_tablos_test.go + - backend/internal/web/router.go + - .planning/phases/12-native-tablo-chat/12-UI-SPEC.md + + + Add DB-backed full-router tests that initially fail before implementation: + 1. `TestDiscussionTabRendersHistoryAndComposer` creates two messages with HTML-looking body text, requests `GET /tablos/{id}/discussion`, and expects Discussion, `1 participant`, oldest-first ordering, author email, absolute timestamp content, escaped text, day separator, textarea `Message`, placeholder `Write a message...`, and `Send message`. + 2. `TestDiscussionTabFullPageFallback` sends a non-HTMX direct GET and expects the full tablo detail shell with Discussion active. + 3. `TestDiscussionPostCreatesMessage` obtains CSRF, posts a valid body with `HX-Request:true`, expects 200, the new message fragment, and a DB row for the authenticated author/tablo. + 4. `TestDiscussionPostRejectsEmptyAndTooLong` expects 422 plus `Message is required.` and `Message is too long.`. + 5. `TestDiscussionOwnershipReturns404` verifies another user cannot GET or POST to the owner's discussion. + 6. `TestDiscussionRequiresCSRF` posts without CSRF and expects gorilla/csrf rejection. + + + cd backend && go test ./internal/web -run 'TestDiscussion' -count=1 + + + - Tests use the existing session/CSRF/full-router helper patterns. + - Tests prove body escaping by asserting raw `