---
phase: 05-files
plan: 04
type: execute
wave: 4
depends_on:
  - "05-03"
files_modified: []
autonomous: false
requirements:
  - FILE-01
  - FILE-02
  - FILE-03
  - FILE-04
  - FILE-05
  - FILE-06

must_haves:
  truths:
    - "Tab navigation updates browser URL via hx-push-url when switching between Overview, Tasks, and Files tabs"
    - "A file can be uploaded, appears in the list with correct filename and human-readable size, and the download link delivers the file"
    - "Deleting a file removes it from the list immediately; refreshing the page confirms it is gone"
    - "Uploading a file >25MB shows a friendly error message above the form without crashing"
    - "Only the tablo owner can upload/list/download/delete files (verified by navigating to another user's tablo)"
  artifacts: []
  key_links: []
---

<objective>
Human-verify checkpoint: full end-to-end browser walkthrough of the Phase 5 file workflow. Covers all six FILE requirements through manual interaction using the local MinIO + Go server stack.

Purpose: Phase 5 success criteria require browser-level verification of tab navigation URL updates, file upload/list/download/delete flow, size enforcement, and visual polish that cannot be asserted in unit tests.
Output: User approval or a list of issues for gap closure.
</objective>

<execution_context>
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.claude/get-shit-done/workflows/execute-plan.md
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/ROADMAP.md §Phase 5 Success Criteria
@/Users/arthur.belleville/Documents/perso/projects/xtablo-source/.planning/phases/05-files/05-CONTEXT.md
</context>

<tasks>

<task type="auto">
  <name>Task 1: Automated pre-flight before browser session</name>
  <files></files>
  <read_first>
    backend/.env — confirm S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, MAX_UPLOAD_SIZE_MB are set (or .env.local)
  </read_first>
  <action>
    Run these commands and confirm all pass before handing off to the user:

    1. Full test suite: cd backend && go test ./... -count=1 -timeout 60s — must exit 0
    2. Migration check: cd backend && just migrate-status (or goose -dir migrations postgres $DATABASE_URL status) — confirm 0005_files appears in Applied list
    3. Build check: cd backend && go build ./cmd/web/. — must exit 0
    4. Compose services: cd backend && podman-compose up -d (or docker compose up -d) — postgres and minio must reach "healthy" state
    5. Start server: cd backend && just dev (or equivalent) — server must start on :8080 without error

    If any step fails, fix the issue before proceeding to the human-verify checkpoint.
  </action>
  <verify>
    <automated>cd /Users/arthur.belleville/Documents/perso/projects/xtablo-source/backend && go test ./... -count=1 -timeout 60s && go build ./cmd/web/. && echo "PRE-FLIGHT OK"</automated>
  </verify>
  <done>
    go test ./... exits 0. go build ./cmd/web/. exits 0. Server starts without errors.
  </done>
  <acceptance_criteria>
    - go test ./... exits 0
    - go build ./cmd/web/. exits 0
    - Server starts (no panic on startup)
  </acceptance_criteria>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <what-built>
    Phase 5 complete: file upload (server-proxied, streaming to MinIO), file list (filename + size + date), signed-URL download (302 redirect, 5-minute TTL), inline-confirm delete, 3-tab tablo detail page with hx-push-url.

    Start the Go server with MinIO running (just dev or go run ./cmd/web/.) then complete these checks:
  </what-built>
  <how-to-verify>
    **Step 1 — Tab navigation (D-07, D-08)**
    1. Log in and open any tablo detail page: http://localhost:8080/tablos/{id}
    2. Verify a tab bar is visible with three tabs: Overview, Tasks, Files
    3. Click the Tasks tab — verify URL changes to /tablos/{id}/tasks and the kanban board loads
    4. Click the Files tab — verify URL changes to /tablos/{id}/files and the upload form appears
    5. Click Overview — verify URL changes back to /tablos/{id} and the tablo title/description appear
    6. Hit browser Back button from Tasks — verify URL and content revert correctly

    **Step 2 — File upload (FILE-01, FILE-02, D-05, D-09)**
    7. On the Files tab, attach any small file (PDF, image, or text) using the upload form and click Upload
    8. Verify the file appears in the list below the form with: original filename, human-readable size (e.g. "42.5 KB"), and an upload date
    9. Upload the same file again — verify it appears twice (D-06: no dedup, each gets its own row)
    10. Attempt to upload a file larger than 25MB (or rename a large file to test); verify a friendly error message appears above the form — NOT a blank page or 500 error

    **Step 3 — File download (FILE-04)**
    11. Click the download link for any uploaded file
    12. Verify the browser either downloads the file directly or opens it in a new tab (the presigned URL redirects to MinIO — may require allowing the MinIO redirect from localhost:9000)
    13. Verify the download completes successfully

    **Step 4 — File delete (FILE-05)**
    14. Click the delete button on a file row
    15. Verify an inline confirmation appears ("Delete file?", filename, Yes-delete + Keep file buttons)
    16. Click "Keep file" — verify the row is restored to normal
    17. Click delete again, then "Yes, delete" — verify the row disappears from the list immediately
    18. Refresh the page — verify the deleted file is still gone from the list

    **Step 5 — Authorization (FILE-06)**
    19. If possible, open the browser in an incognito window, log in as a different user (sign up a second account), and attempt to navigate to the first user's tablo files URL: http://localhost:8080/tablos/{first_user_tablo_id}/files
    20. Verify you get a 404 (not a file list)

    **Step 6 — Kanban regression check (TASK-01..07)**
    21. Click the Tasks tab on any tablo
    22. Create a task, move it to a different column, verify it persists after refresh
    23. This confirms tab restructuring has not broken the kanban board
  </how-to-verify>
  <resume-signal>Type "approved" if all steps pass. Describe any issues found (reference step numbers) if anything fails.</resume-signal>
</task>

</tasks>

<threat_model>
## Trust Boundaries

| Boundary | Description |
|----------|-------------|
| Local MinIO → browser | 302 redirect from Go server to MinIO at localhost:9000; browser follows redirect |

## STRIDE Threat Register

| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-05-04-01 | Information Disclosure | MinIO console at localhost:9001 | accept | Dev-only; minioadmin/minioadmin credentials are known defaults; not exposed in production |
</threat_model>

<verification>
Phase 5 is verified complete when:
- Checkpoint approved by user (all 6 browser steps pass)
- go test ./... exits 0 (confirmed in Task 1 pre-flight)
- All six FILE-01..06 requirements exercised and observed working in browser
</verification>

<success_criteria>
1. User explicitly types "approved" after completing all verification steps
2. No regressions in kanban board behavior (TASK-01..07 spot-checked in Step 6)
3. Tab navigation works with hx-push-url URL updates
4. Upload → list → download → delete full cycle works end-to-end
5. Oversize upload shows friendly error (not 500)
6. Authorization: non-owner gets 404 on file routes
</success_criteria>

<output>
After completion, create .planning/phases/05-files/05-04-SUMMARY.md
</output>
