---
phase: 19-tablo-list-revamp
plan: "01"
subsystem: database
tags: [go, sqlc, goose, postgres, htmx, tablos, progress]

# Dependency graph
requires:
  - phase: 18-app-shell-navigation
    provides: App shell and navigation wiring this plan builds on top of
provides:
  - Reversible goose migration adding status column (text NOT NULL DEFAULT 'active') to tablos with CHECK constraint
  - Regenerated sqlc types: Tablo.Status string field on the Tablo struct
  - ListTabloProgressByIDs batch SQL query returning done_tasks/total_tasks per tablo
  - TabloCardView.Progress int field (0-100)
  - TablosListHandler wired with one-query-per-page batch progress fetch
affects: [19-02, 19-03, any plan reading TabloCardView or sqlc.Tablo]

# Tech tracking
tech-stack:
  added: []
  patterns:
    - Batch aggregation query pattern (D-06): fetch all progress in one SQL query instead of N+1
    - Non-fatal progress fetch: log error and proceed with Progress=0 rather than 500

key-files:
  created:
    - backend/migrations/0010_tablo_status.sql
  modified:
    - backend/internal/db/queries/tablos.sql
    - backend/templates/discussion_forms.go
    - backend/internal/web/handlers_tablos.go

key-decisions:
  - "Tablo status column: text NOT NULL DEFAULT 'active' CHECK IN ('active','archived') — DB-enforced invariant (T-19-01-01)"
  - "Progress batch query using ANY(@tablo_ids::uuid[]) with pgx/v5 native uuid[] handling — no N+1"
  - "sqlc-generated Go files are gitignored and regenerated at build time — committed SQL source only"
  - "Non-fatal progress query: error logged but handler continues with Progress=0 (D-05)"

patterns-established:
  - "Batch aggregation: collect IDs after primary query, run one aggregation, build progressMap, populate slice in a final loop"
  - "Non-fatal secondary queries: slog.Error + nil slice fallback pattern, consistent with sidebar tablo fetch in TabloDetailHandler"

requirements-completed: [LIST-01, LIST-03]

# Metrics
duration: 15min
completed: 2026-05-17
---

# Phase 19 Plan 01: Tablo List Revamp — Data Layer Summary

**goose migration adds `status` column to tablos, sqlc regenerated with Status string field and ListTabloProgressByIDs batch query, TabloCardView enriched with Progress int, handler wired with single-query-per-page progress fetch**

## Performance

- **Duration:** ~15 min
- **Started:** 2026-05-17T16:20:00Z
- **Completed:** 2026-05-17T16:35:00Z
- **Tasks:** 2
- **Files modified:** 4 (2 tracked: queries/tablos.sql, migrations/0010_tablo_status.sql; 2 gitignored sqlc regen: models.go, tablos.sql.go)

## Accomplishments
- Migration 0010 adds `status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived'))` to tablos; DB-enforced constraint (T-19-01-01)
- All tablo SQL queries updated with `status` column in SELECT/RETURNING/GROUP BY; sqlc regenerated cleanly
- Batch progress query `ListTabloProgressByIDs` runs once per dashboard load (D-06), not N+1
- `TabloCardView.Progress int` field and handler wiring ready for Plans 02/03 template rendering

## Task Commits

Each task was committed atomically:

1. **Task 1: Migration, SQL query updates, and sqlc regeneration** - `c1928e3` (feat)
2. **Task 2: Enrich TabloCardView and wire progress in handler** - `47ba2f1` (feat)

**Plan metadata:** committed with SUMMARY

## Files Created/Modified
- `backend/migrations/0010_tablo_status.sql` - Reversible goose migration adding status column to tablos
- `backend/internal/db/queries/tablos.sql` - All tablo queries updated with status column; new ListTabloProgressByIDs batch query
- `backend/templates/discussion_forms.go` - TabloCardView gains Progress int; TabloCardsFromUnreadRows maps row.Status
- `backend/internal/web/handlers_tablos.go` - TablosListHandler calls ListTabloProgressByIDs, populates cardViews[i].Progress

## Decisions Made
- Used `ANY(@tablo_ids::uuid[])` array parameter — pgx/v5 handles `[]uuid.UUID` natively without requiring a sqlc.yaml override
- Confirmed sqlc-generated Go files are gitignored (`.gitignore: internal/db/sqlc/*.go`); committed SQL source only
- Kept progress fetch non-fatal to match existing pattern in `TabloDetailHandler` sidebar fetch

## Deviations from Plan

None - plan executed exactly as written.

## Issues Encountered
- sqlc-generated `.go` files are listed under `.gitignore` with `internal/db/sqlc/*.go` — only SQL source files and migration committed; no action needed (working as designed)

## Next Phase Readiness
- Data layer is complete: `Tablo.Status`, `TabloCardView.Progress`, and `ListTabloProgressByIDs` are all wired
- Plans 02 and 03 can read `cardViews[i].Progress` and `cardViews[i].Tablo.Status` for template rendering
- No blockers

---
*Phase: 19-tablo-list-revamp*
*Completed: 2026-05-17*
