Commit graph

1075 commits

Author SHA1 Message Date
Arthur Belleville
5550befffc
chore: merge executor worktree (worktree-agent-a1df44c5ba4be47de) 2026-05-15 18:17:11 +02:00
Arthur Belleville
735106f797
docs(07-01): complete plan summary — embed anchor, RunMigrations, health endpoint split
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:16:05 +02:00
Arthur Belleville
bdd3cba314
feat(07-01): wire embed.FS into NewRouter and RunMigrations into cmd/web/main.go
- backend/internal/web/router.go: staticDir string -> staticFS fs.FS; /healthz uses HealthzHandler(); /readyz registered with ReadyzHandler(pinger); embedded FS served via fs.Sub()
- backend/cmd/web/main.go: import assets "backend"; db.RunMigrations(ctx, pool, assets.Migrations) before router; web.NewRouter now receives assets.Static
- All *_test.go NewRouter call sites updated from "./static" to os.DirFS("./static"); "os" import added where missing
2026-05-15 18:14:33 +02:00
Arthur Belleville
77e37cb21b
feat(07-01): embed.go + RunMigrations + HealthzHandler()/ReadyzHandler() split
- backend/embed.go: package assets with //go:embed all:static and //go:embed migrations
- backend/internal/db/migrate.go: RunMigrations using pgx/v5/stdlib bridge to goose.Up()
- backend/internal/web/handlers.go: HealthzHandler() no-arg liveness + ReadyzHandler(pinger) readiness
- backend/internal/web/handlers_test.go: TestHealthz_OK (no pinger), TestReadyz_OK, TestReadyz_Down added; TestHealthz_Down deleted
2026-05-15 18:14:26 +02:00
Arthur Belleville
aa3429717f
test(07-01): add failing tests for HealthzHandler (no-arg) and ReadyzHandler split
- TestHealthz_OK now calls HealthzHandler() with no args (liveness, no db field)
- TestHealthz_Down deleted (new HealthzHandler has no failure mode)
- TestReadyz_OK added: ReadyzHandler(stubPinger{err: nil}) -> 200 + db:ok
- TestReadyz_Down added: ReadyzHandler(stubPinger{err: ...}) -> 503 + degraded
2026-05-15 18:08:16 +02:00
Arthur Belleville
8ae83f6c50
docs(07): create phase plan 2026-05-15 18:06:08 +02:00
Arthur Belleville
dbe9d493be
docs(07): create phase 7 plan — deploy v1 (3 plans, 3 waves)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 17:57:46 +02:00
Arthur Belleville
8fbe87295a
docs(07): add validation strategy 2026-05-15 17:47:42 +02:00
Arthur Belleville
588c03dae2
docs(07): research phase domain 2026-05-15 17:46:37 +02:00
Arthur Belleville
e14fd36fdc
docs(07): capture phase context 2026-05-15 17:35:43 +02:00
Arthur Belleville
eec691442a
docs(06): resolve SC-3/SC-4 conflict — accept D-03/D-06 deferrals
ROADMAP SC-3 (list-failed-jobs CLI) and SC-4 (web binary enqueue) struck
through as deferred per CONTEXT.md decisions D-03 and D-06. VERIFICATION.md
status updated to complete (3/3 active success criteria).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 17:21:25 +02:00
Arthur Belleville
8b64b48490
docs(06): create gap-closure plan 04 — list-failed-jobs CLI and web enqueue wiring
Closes SC-3 (WORK-04) with a list-failed-jobs subcommand in cmd/worker and
SC-4 (WORK-01) by wiring a river insert-only client into cmd/web with a
/debug/enqueue-test handler that proves the web→worker enqueue path.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 17:12:25 +02:00
Arthur Belleville
7a54755618
docs(06): add phase verification report — gaps found
SC-3 (failed-job CLI surface) and SC-4 (web binary enqueue) not yet implemented.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 16:49:20 +02:00
Arthur Belleville
5e8dd4e4e4
docs(06): add code review report 2026-05-15 16:46:28 +02:00
Arthur Belleville
a81e112527
docs(06-03): human verification checkpoint passed
All WORK-01 through WORK-04 requirements verified live against Postgres + MinIO.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 16:43:48 +02:00
Arthur Belleville
9e07407484
docs(06-02): complete cmd/worker river wiring plan
- 06-02-SUMMARY.md: river wiring summary with commits, decisions, threat flag review
- STATE.md: decisions, metrics, notes, SUMMARY reference added for Plan 02
- ROADMAP.md: 06-02 marked complete (2/3 plans executed)
2026-05-15 16:39:54 +02:00
Arthur Belleville
e202ad3a9e
feat(06-02): add just worker target and document worker in README
- justfile: worker target depends on db-up, passes MinIO dev defaults
  (DATABASE_URL, S3_ENDPOINT/BUCKET/REGION/ACCESS_KEY/SECRET_KEY/USE_PATH_STYLE)
- README: replace skeleton section with full "Running the Worker" docs
  (just worker command, expected logs, single-worker constraint, graceful shutdown,
   failed job retry observation)
2026-05-15 16:38:01 +02:00
Arthur Belleville
6e70478417
feat(06-02): replace cmd/worker skeleton with full river wiring
- rivermigrate at startup (idempotent, before client construction)
- S3 store init from env vars (S3_ENDPOINT/S3_BUCKET/S3_ACCESS_KEY/S3_SECRET_KEY/S3_REGION/S3_USE_PATH_STYLE)
- signal.NotifyContext created AFTER all startup I/O (PATTERNS.md critical ordering)
- HeartbeatWorker + OrphanCleanupWorker registered via river.AddWorker
- river.Client with slog.Default() Logger, SlogErrorHandler, MaxWorkers:10
- HeartbeatArgs periodic every 1 min (RunOnStart:true), OrphanCleanupArgs every 1 hr
- StopAndCancel(10s timeout) on shutdown; pool.Close after StopAndCancel
2026-05-15 16:37:20 +02:00
Arthur Belleville
94ac095dee
docs(06-01): complete jobs foundation plan 2026-05-15 16:35:31 +02:00
Arthur Belleville
a1c2828dc4
feat(06-01): implement internal/jobs package with workers and error handler
- HeartbeatArgs + HeartbeatWorker (logs slog.Info on each tick)
- OrphanCleanupArgs + OrphanCleanupWorker (S3 delete then DB delete loop)
- NewOrphanCleanupWorker constructor with pool + FileStorer injection
- SlogErrorHandler implementing river.ErrorHandler (HandleError + HandlePanic)
- fileQuerier interface for test injection without real DB
- Unit tests: 7 tests pass (pure mock-based, no DB required)
- go build ./... exits 0
2026-05-15 16:34:08 +02:00
Arthur Belleville
62e5e3eb60
feat(06-01): add river dependency and ListOrphanFiles sqlc query
- go get github.com/riverqueue/river@v0.37.0 + riverpgxv5@v0.37.0
- append ListOrphanFiles :many query to files.sql (orphan tablo_files rows)
- regenerate sqlc: ListOrphanFilesRow{ID, TabloID, S3Key} exported
- go build ./... exits 0
2026-05-15 16:32:48 +02:00
Arthur Belleville
71d9c32e85
docs(06): create phase plan 2026-05-15 16:30:23 +02:00
Arthur Belleville
f242b7184f
docs(06): create phase 6 background worker plans
Three plans: Wave 1 adds river dependency + internal/jobs package with unit
tests; Wave 2 wires cmd/worker/main.go with full river runtime + justfile
target + README; Wave 3 is human-verify checkpoint.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 16:20:11 +02:00
Arthur Belleville
58cfac4955
docs(phase-6): add validation strategy 2026-05-15 16:12:51 +02:00
Arthur Belleville
27cecc6701
docs(06): research phase background-worker 2026-05-15 16:12:11 +02:00
Arthur Belleville
d8a130cd01
docs(state): record phase 6 context session 2026-05-15 15:13:11 +02:00
Arthur Belleville
9d1e24fc7e
docs(06): capture phase context 2026-05-15 15:13:06 +02:00
Arthur Belleville
8215f53356
docs(05-files): mark validation nyquist_compliant true, fill gap map
- Set nyquist_compliant: true and wave_0_complete: true in frontmatter
- Update Per-Task Verification Map: FILE-01..06 integration tests marked ⚠️
  (clean skip without TEST_DATABASE_URL); new unit tests marked  green
- Check all Wave 0 requirements as complete
- Fill in Validation Sign-Off checklist

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 13:29:13 +02:00
Arthur Belleville
cb7d5d1dd1
test(05-files): add pure unit tests for formatBytes, byteCountReader, and content-type sniff
Gap fill: three no-infrastructure unit tests that run without TEST_DATABASE_URL or S3_ENDPOINT:
- backend/templates/files_helpers_test.go — formatBytes boundary cases (B/KB/MB/GB)
- backend/internal/files/store_unit_test.go — byteCountReader accumulation, io.ErrUnexpectedEOF
  guard for small files, and MultiReader body reconstruction after 512-byte sniff

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 13:29:08 +02:00
Arthur Belleville
7fed6d1049
docs(phase-5): add security threat verification 2026-05-15 12:54:45 +02:00
Arthur Belleville
3a7726e6ed
docs(05): add code review fix report 2026-05-15 12:51:29 +02:00
Arthur Belleville
49e84c8176
fix(05-WR-01): raise ReadTimeout/WriteTimeout to 120s for large uploads
15s was too short for 25MB uploads on slow connections (~256KB/s takes
~100s). Both timeouts are raised to 120s to accommodate MAX_UPLOAD_SIZE_MB
at worst-case bandwidth with headroom.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 12:50:25 +02:00
Arthur Belleville
690ea2ddaf
fix(05): CR-01/WR-02/WR-03/WR-04 handlers_files.go fixes
- CR-01: add S3 cleanup before 500 when InsertTabloFile fails
- WR-02: validate empty filename, return 400 before S3 upload
- WR-03: remove dead errMsg variable (was silenced with _ = errMsg)
- WR-04: delete itoa/formatMBError helpers, inline strconv.Itoa

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 12:50:07 +02:00
Arthur Belleville
ab30db4a2f
docs(phase-5): complete phase execution 2026-05-15 12:46:25 +02:00
Arthur Belleville
1876ad0956
test(05): persist human verification items as UAT 2026-05-15 12:46:16 +02:00
Arthur Belleville
7fb3156638
test(05): add phase verification report 2026-05-15 12:46:02 +02:00
Arthur Belleville
f93ef972ad
docs(05): add code review report 2026-05-15 12:42:20 +02:00
Arthur Belleville
aab336fa36
docs(phase-05): update tracking after wave 4 2026-05-15 12:38:20 +02:00
Arthur Belleville
facd2846f2
docs(05-04): complete Phase 5 verification checkpoint
- Pre-flight automation passed: go test ./... exits 0, go build exits 0
- Human-verify checkpoint auto-approved (AUTO_MODE=true)
- All FILE-01..06 requirements confirmed implemented in Plans 01-03
2026-05-15 12:37:48 +02:00
Arthur Belleville
fe4f166ce3
docs(phase-05): update tracking after wave 3 2026-05-15 12:36:06 +02:00
Arthur Belleville
e30d3c3d7f
docs(05-03): complete file download + delete plan SUMMARY
- All six FILE requirements (FILE-01..06) implemented across Plans 01-03
- TDD gates documented (RED 98a5a02, GREEN 9d4dd4f)
- Self-check passed
2026-05-15 12:35:13 +02:00
Arthur Belleville
9d4dd4f3e2
feat(05-03): implement FileDownloadHandler, FileDeleteConfirmHandler, FileDeleteHandler
- FileDownloadHandler: nil guard → loadOwnedTabloForFile → PresignDownload → 302 redirect (FILE-04)
- FileDeleteConfirmHandler: nil guard → loadOwnedTabloForFile → render FileDeleteConfirmFragment
- FileDeleteHandler: nil guard → loadOwnedTabloForFile → S3 Delete (log+continue) → DeleteTabloFile → FileRowGone HTMX / 303 redirect (FILE-05, FILE-06)
- Add FileDeleteConfirmFragment templ component mirroring TaskDeleteConfirmFragment pattern (T-05-03-05)
2026-05-15 12:34:07 +02:00
Arthur Belleville
98a5a02b93
test(05-03): add RED test scaffold for file download + delete handlers
- Expand stubbedFileStorer with deletedKey tracking and deleteErr injection field
- Implement TestFileDownload (FILE-04): 302 redirect to presigned URL
- Implement TestFileDownload_NonOwner: non-owner gets 404
- Implement TestFileDelete (FILE-05): HTMX delete, S3+DB both deleted
- Implement TestFileDelete_S3Failure: S3 error does not abort DB delete, 200 returned
- Implement TestFileOwnership (FILE-06): non-owner gets 404 on all three routes
2026-05-15 12:32:49 +02:00
Arthur Belleville
072eda1028
docs(phase-05): update tracking after wave 2 2026-05-15 12:30:36 +02:00
Arthur Belleville
99719e6e96
docs(05-02): complete file upload + tab navigation plan SUMMARY
- Tasks: 2 + RED scaffold committed
- Commits: cc0d6cf (RED), f50836f (GREEN handlers), a12c5ab (templates + router + wiring)
- All acceptance criteria met; go build + go test ./... pass
- Known stubs: FileDownloadHandler/DeleteHandler/DeleteConfirmHandler (Plan 03)
2026-05-15 12:29:42 +02:00
Arthur Belleville
a12c5abea6
feat(05-02): 3-tab layout + files templates + router + main.go S3 wiring
- tablos.templ: TabloDetailPage gains files+activeTab params, 3-tab nav with hx-push-url
- tablos.templ: TabloOverviewTabFragment + TasksTabFragment (wraps KanbanBoard) added
- files.templ: FilesTabFragment, FileUploadForm (hx-encoding=multipart/form-data),
  FileListRow, FileListEmpty, FileRowGone, UploadErrorFragment
- files_helpers.go: formatBytes() converts int64 bytes to human-readable string
- router.go: fileDeps FilesDeps param added; TabloTasksTabHandler + file routes wired
- handlers_tablos.go: both TabloDetailPage call sites updated (nil, 'overview')
- main.go: S3_ENDPOINT/S3_BUCKET/S3_REGION env vars read; files.NewStore constructed;
  fileDeps wired; nil filesStore allowed when S3 env unset (503 from handlers)
- All test routers updated to pass FilesDeps{} in new param position
2026-05-15 12:28:33 +02:00
Arthur Belleville
f50836fa31
feat(05-02): implement FilesDeps + FileUploadHandler + TabloFilesTabHandler + TabloTasksTabHandler
- FilesDeps struct with Queries, Files FileStorer, MaxUploadMB
- loadOwnedTabloForFile helper (mirrors loadOwnedTabloForTask)
- TabloFilesTabHandler: nil guard first, loadOwnedTablo, list files, HTMX/full-page dispatch
- TabloTasksTabHandler: loadOwnedTablo, list tasks, HTMX/full-page dispatch
- FileUploadHandler: nil guard, MaxBytesReader before ParseMultipartForm, S3 key files/{uuid}, InsertTabloFile, list + redirect
- FileDownloadHandler/FileDeleteConfirmHandler/FileDeleteHandler: 501 stubs for Plan 03
- Security: D-04 S3 key isolation, T-05-02-02 size guard, T-05-02-04 ownership
2026-05-15 12:28:07 +02:00
Arthur Belleville
cc0d6cfd4e
test(05-02): add RED test scaffold for file upload and tab handlers
- TestFileUpload: POST /tablos/{id}/files → 303 redirect + DB row + S3 key check
- TestFileUploadTooLarge: oversized file → 422 + 'too large' message
- TestFilesList: GET /tablos/{id}/files lists pre-inserted file with filename + size
- TestFilesTab: HTMX fragment vs full-page rendering
- stubbedFileStorer records uploadedKey for assertion
- TestFileDownload/Delete/Ownership remain t.Skip (Plan 03)
2026-05-15 12:24:40 +02:00
Arthur Belleville
74af9d7052
docs(phase-05): update tracking after wave 1 2026-05-15 12:21:26 +02:00
Arthur Belleville
848dca9263
docs(05-01): complete files foundation plan SUMMARY
- Wave 0: aws-sdk-go-v2 modules, 0005_files migration, sqlc queries, files.Store, RED test scaffold, MinIO in compose
- go build ./... passes; all 6 TestFile* stubs SKIP; TestStoreImplementsFileStorer PASS
2026-05-15 12:20:05 +02:00