# Tasks: add-import-sse-progress ## 1. OTel — extend instruments bundle - [x] Add `sseConnected: Counter` (`import.sse.connected`) to `ImportInstruments`. - [x] Add `sseEventsSent: Counter` (`import.sse.events_sent`) labelled by `kind`. - [x] Add `sseDisconnected: Counter` (`import.sse.disconnected`) labelled by `reason`. - [x] Update `src/otel/instruments.md` to describe the three new counters. - [x] Extend `src/otel/instruments.test.ts` to assert the new counters round-trip through a fresh `MeterProvider`. ## 2. Route — `GET /:id/progress` - [x] Create `src/routes/progress-sse/progress-sse.ts` exporting `createProgressSseHandler(deps)`. - [x] Wire the handler into `createImportRoutes` in `src/routes/build-routes.ts`. - [x] Subscribe to `service.bus` (`import.progress`, `import.completed`, `import.failed`) — NO polling. - [x] Forward the request `AbortSignal` to detach the listener on client disconnect. - [x] Frame format: `id: -`, `event: progress|complete|failed`, JSON-stringified `ImportProgress` payload, double-newline terminator. - [x] Initial frame: snapshot from `service.getJob(id, ownerId)` so the client sees current state before the first bus tick. - [x] Terminal events (`complete` / `failed`) close the stream cleanly. ## 3. Errors - [x] Reuse `IMPORT.NOT_FOUND` for foreign-owner / missing jobs (404 problem+json). - [x] Reuse `AUTH.UNAUTHENTICATED` (via `requireAuth()` middleware already in `build-routes.ts`) for the 401 path. - [x] No new error codes added. ## 4. Tests - [x] `src/routes/progress-sse/progress-sse.test.ts` covering all eight canonical scenarios plus four coverage-completion scenarios (terminal initial state, signal pre-aborted, foreign-job filter, post-terminal abort idempotency, abort-mid-stream). - [x] Tests use Hono's `app.request()` returning a `Response` with a streamed body; assertions read via `body.getReader()` and decode UTF-8. - [x] No mocks. Real `ImportService`, real Hono, real in-memory `MeterProvider`. ## 5. Docs - [x] `src/routes/progress-sse/progress-sse.md` (≥200 words, Purpose / Features / Usage Basic / Usage Advanced / API Reference / Implementation Notes). - [x] Update `src/otel/instruments.md` Features list and API Reference for the three new counters. ## 6. Subpath export - [x] Add `./routes/progress-sse/progress-sse` to `package.json#exports`. ## 7. Gates (in order) - [x] `bunx biome check src/` — clean. - [x] `bunx turbo lint typecheck test --filter=@suaveplan/api-plugin-import` — green. - [x] `bunx turbo test:coverage --filter=@suaveplan/api-plugin-import` — 100/100/100/100. - [x] `bun scripts/openspec-conformance.ts @suaveplan/api-plugin-import` — 0 errors. - [x] `bunx turbo build --filter=@suaveplan/api-plugin-import` — green. ## 8. Archive - [x] Fold spec delta into `openspec/specs/api-plugin-import/spec.md`. - [x] `mv openspec/changes/add-import-sse-progress openspec/archive/2026-05-20-add-import-sse-progress`.