Skip to content

UI-SP5c — Tasks-list SSE follow-on (view-free)#24

Merged
l17728 merged 6 commits into
mainfrom
feat/ui-sp5c-tasks-list-sse
May 20, 2026
Merged

UI-SP5c — Tasks-list SSE follow-on (view-free)#24
l17728 merged 6 commits into
mainfrom
feat/ui-sp5c-tasks-list-sse

Conversation

@l17728
Copy link
Copy Markdown
Owner

@l17728 l17728 commented May 20, 2026

Summary

Third application of the view-free SSE template (after SP5 task-detail #22 and SP5b executors #23). useTaskList (consumed by both TaskList.vue and the Dashboard "recent tasks" widget) now talks SSE; both views unchanged.

  • Backend: GET /api/v1/tasks/stream — hand-rolled text/event-stream mirroring SP5/SP5b. Reuses SP1's list_tasks aggregation (tenant_filtered(select(DownloadTask)) + total = count()). 5 s default tick clamp [0.5, 60.0]. Same ?max_ticks=N testability hatch.
  • Frontend: useTaskList opts in via the SP5-shipped streamUrl+applyEvent seam — signature/return unchanged. TaskList.vue + Dashboard.vue NOT modified.

Pre-review found 2 real BLOCKERs (first-of-kind for this template)

  1. Route collision: /api/v1/tasks/stream lives in a separate router with the same /api/v1/tasks prefix as tasks_router (which has /{task_id}). FastAPI iterates routers in include order — if tasks_router came first, GET /tasks/stream would match /{task_id} → 422 UUID parse. SP5/SP5b didn't expose this because their stream paths had no sibling parameterized routes under the same prefix. Fix: register tasks_list_stream_router BEFORE tasks_router in src/dlw/main.py + comment explaining the invariant.
  2. Missing User(id=2) seed: cross-tenant test POSTs as user_id=2; bootstrap previously only seeded User(id=1) → FK violation. Fix: bootstrap seeds both.

A third IMPORTANT was also fixed (cross-tenant test used storage_id=1 for the tenant-2 task; now uses storage_id=2).

These three pre-review catches reinforce the value of the 2-opus gate — even on what looked like a near-trivial template repeat.

Verification

  • Backend: 459 pytest (455 prior + 4 new SP5c: unauth/tenant-isolation/multi-snapshot/slim-shape).
  • Frontend: 149 vitest (147 prior + 2 new SP5c).
  • vue-tsc strict 0; eslint --max-warnings=0; vite build ok. spectral/swagger/invariant/status-write all green.
  • Live headed Playwright smoke: /api/v1/tasks/stream SSE request observed in DevTools network on the /tasks page; zero real console errors.
  • View-free proof: git diff af48a0a..HEAD -- frontend/src/pages/TaskList.vue frontend/src/pages/Dashboard.vue returns empty.
  • Final opus review: MERGE-READY (0 CRITICAL/HIGH; 1 LOW = inherited _KEEPALIVE_EVERY_TICKS vestige).

Test plan

  • CI green
  • Squash-merge with --delete-branch

🤖 Generated with Claude Code

l17728 and others added 6 commits May 20, 2026 19:19
BLOCKER 1 (first-of-kind for this template): /api/v1/tasks/stream would be
shadowed by /{task_id} (FastAPI iterates routers in include order; "stream"
gets parsed as UUID → 422). SP5/SP5b didn't expose this because their stream
prefixes had no sibling parameterized routes. Fix: register
tasks_list_stream_router BEFORE tasks_router in main.py.

BLOCKER 2: cross-tenant test POSTs as user_id=2 but bootstrap only seeds
User(id=1) → FK violation. Fix: add User(id=2, tenant_id=2) to bootstrap.

IMPORTANT 1: cross-tenant test used storage_id=1 (tenant-1 storage) for the
tenant-2 task. Backend doesn't currently validate but test should be
semantically correct. Fix: parameterize _seed_tasks; pass storage_id=2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@l17728 l17728 merged commit f9ac9ce into main May 20, 2026
12 checks passed
@l17728 l17728 deleted the feat/ui-sp5c-tasks-list-sse branch May 20, 2026 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant