Arthur Belleville
c5477e4ceb
feat(12-01): implement discussion tab and posting
2026-05-16 10:11:14 +02:00
Arthur Belleville
39e21be126
test(12-01): add discussion handler coverage
2026-05-16 10:08:34 +02:00
Arthur Belleville
68884daf11
feat(12-01): add discussion schema and queries
2026-05-16 10:07:12 +02:00
Arthur Belleville
bb84d70569
fix(11-02): show planning event dates
2026-05-16 08:39:10 +02:00
Arthur Belleville
2989c0b917
feat(11-01): implement planning agenda page
2026-05-16 07:26:49 +02:00
Arthur Belleville
c5c3bbe2d0
test(11-01): add planning agenda red coverage
2026-05-16 07:24:23 +02:00
Arthur Belleville
1d760d5540
test(10-04): add final events regression coverage
2026-05-16 00:36:40 +02:00
Arthur Belleville
ebd31b5645
feat(10-03): add event navigation and user range query
2026-05-16 00:35:09 +02:00
Arthur Belleville
0692dd2d4f
test(10-03): add failing event navigation query tests
2026-05-16 00:34:31 +02:00
Arthur Belleville
614003f165
feat(10-02): add event edit and delete flows
2026-05-16 00:32:55 +02:00
Arthur Belleville
e5f083d2a8
test(10-02): add failing event mutation tests
2026-05-16 00:30:52 +02:00
Arthur Belleville
0bfe8cfbb4
feat(10-01): add events calendar creation slice
2026-05-16 00:27:58 +02:00
Arthur Belleville
4fbd960621
test(10-01): add failing events create calendar tests
2026-05-16 00:24:33 +02:00
Arthur Belleville
f9fc7a1e34
fix(09): honor selected etape on task create
2026-05-15 23:46:32 +02:00
Arthur Belleville
ee62ff9f9b
fix(09): refresh etape counts on task delete
2026-05-15 23:02:05 +02:00
Arthur Belleville
0c95049447
fix(09): refresh etape counts on task create
2026-05-15 22:59:01 +02:00
Arthur Belleville
cf07c29ae5
test(09-04): harden db-backed regressions
2026-05-15 22:54:46 +02:00
Arthur Belleville
55263e4a52
test(09-04): add etape reorder regressions
2026-05-15 22:49:09 +02:00
Arthur Belleville
b22d79d972
feat(09-03): add task etape selector
2026-05-15 22:47:56 +02:00
Arthur Belleville
9f6c7eb044
test(09-03): add task etape assignment tests
2026-05-15 22:46:14 +02:00
Arthur Belleville
4af623a57b
feat(09-02): manage etapes
2026-05-15 22:44:50 +02:00
Arthur Belleville
9b89282692
test(09-02): add etape management tests
2026-05-15 22:42:39 +02:00
Arthur Belleville
565bb88df5
feat(09-01): add etape task slice
2026-05-15 22:40:25 +02:00
Arthur Belleville
a8a3e5f596
test(09-01): add failing etape slice tests
2026-05-15 22:33:40 +02:00
Arthur Belleville
90af9bdaef
feat(08): disable apple sign-in
2026-05-15 21:41:22 +02:00
Arthur Belleville
6e6583636f
feat(08-05): add linked providers view and provider docs
2026-05-15 21:10:45 +02:00
Arthur Belleville
59fd6b15b5
feat(08-04): show social sign-in controls on auth pages
2026-05-15 21:09:14 +02:00
Arthur Belleville
a8b6a03eac
feat(08-03): add apple social sign-in flow
2026-05-15 21:06:08 +02:00
Arthur Belleville
6779663c8a
feat(08-02): add google social sign-in flow
2026-05-15 21:03:30 +02:00
Arthur Belleville
2d004cd251
feat(08-01): add social identity schema foundation
2026-05-15 20:59:34 +02:00
Arthur Belleville
3998a5ab92
Made various improvements to the file management
2026-05-15 19:57:46 +02:00
Arthur Belleville
4ea4d28e6e
fix(07): WR-05 sanitize upload filename with filepath.Base and length cap
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:56:11 +02:00
Arthur Belleville
e7a66c44cf
fix(07): WR-03 add SetMaxOpenConns(2) on migration sql.DB pool
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:55:40 +02:00
Arthur Belleville
ab12bf0962
fix(07): WR-02 move rate limit check before validation in LoginPostHandler
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:55:27 +02:00
Arthur Belleville
b61f36f17e
fix(07): WR-01 NewRouter returns error instead of panicking on bad static FS
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:54:49 +02:00
Arthur Belleville
fbda7cbe5e
fix(07): CR-02 call cancel() explicitly after S3 Delete, not via defer
...
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 18:53:04 +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
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
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
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
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
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
3327a4286d
test(05-01): add RED test scaffold for FILE-01..06 and MinIO in compose.yaml
...
- Create handlers_files_test.go: six TestFile* stubs (all t.Skip), stubbedFileStorer no-op implementing files.FileStorer
- Create store_test.go: compile-time interface assertion, TestNewStore_SkipIfNoEndpoint skips when S3_ENDPOINT unset
- Update compose.yaml: add minio (port 9000/9001) and minio-init services; minio-init uses restart: no (Pitfall 7); add minio_data volume
2026-05-15 12:19:23 +02:00
Arthur Belleville
e0d72747e0
feat(05-01): add aws-sdk-go-v2 modules, 0005_files migration, sqlc queries, and files.Store
...
- Add four aws-sdk-go-v2 modules: core, config, credentials, service/s3
- Write 0005_files.sql migration (tablo_files table with ON DELETE CASCADE)
- Write internal/db/queries/files.sql with InsertTabloFile, ListFilesByTablo, GetTabloFileByID, DeleteTabloFile
- Implement internal/files/store.go: FileStorer interface, Store struct, NewStore (UsePathStyle for MinIO), Upload (sniff+stream+bytecount), Delete, PresignDownload
- sqlc generate produces files.sql.go + TabloFile model (gitignored, regeneratable)
2026-05-15 12:18:16 +02:00
Arthur Belleville
61e6e778e0
fix(04-WR-04): guard against int32 overflow in TaskCreateHandler position arithmetic
...
maxPos + 100 could silently overflow to a negative value when maxPos
approached MaxInt32. Added a maxAllowedPosition guard that returns a
validation error before the InsertTask call if the column position space
is exhausted.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-15 10:19:48 +02:00