Files
manage/openspec/changes/archive/2026-07-09-per-instance-hook-scoping/apply-progress.md
Developer 29650ca512 chore(per-instance-hook-scoping): archive verified+synced change
Move to openspec/changes/archive/2026-07-09-per-instance-hook-scoping/
(R100 renames preserved). 9 artifacts. Canonical openspec/specs/
service-instance-scoping/ remains. Resolves multi-instance wrong-data bug
(hooks now scope by instance.id; instance switcher re-scopes).
Carry-overs: fetchBackupDashboard untouched (design decision 5); subquery
scoping for runs/alerts (schema asymmetry).
2026-07-10 00:17:51 +00:00

46 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Apply Progress: Per-Instance Hook Scoping
**Change:** `per-instance-hook-scoping`
**Phase:** apply-progress
**Date:** 2026-07-09
**Status:** complete — all 17 tasks done, all gates green, verified (see `verify-report.md`)
## Slice delivered
Single slice (commit `3bc7ce5`, +268/73, 12 files) — small correctness fix, well within the 400-line budget.
### Backend
- `routers/backups.py``get_backup_jobs`, `get_backup_runs`, `get_backup_alerts` gain `service_id: str | None = None`; threaded into store calls. `get_backup_dashboard` **NOT touched** (design decision 5 — widget path, PI-117 risk) (PI-110).
- `services/settings_store.py`:
- `list_backup_jobs(service_id=None)` — direct `WHERE service_id = ?` when truthy.
- `list_backup_runs(..., service_id=None)` + `list_backup_alerts(..., service_id=None)` — subquery `job_id IN (SELECT id FROM backup_jobs WHERE service_id = ?)` per the schema asymmetry (only `backup_jobs` has the column; runs/alerts attributed via FK chain).
- Skip filter on None/empty → backward-compat (PI-111, PI-112).
- Tests (`test_backups.py`, +83 lines): `service_id=None` → all; `service_id="X"` → only X's; cross-instance preservation (seed A+B, scope A, confirm B's excluded).
### Frontend
- `hooks/useObservability.ts``useAlertmanagerAlerts`, `useAlertmanagerStatus`, `usePrometheusStatus` gain optional `serviceId` in `queryKey` (`["observability","alerts", serviceId ?? ""]` etc.). `usePrometheusTargets` + `useMonitoringMachines` **unchanged** (global by design — PI-107) (PI-101..PI-104).
- `hooks/useBackups.ts``useBackupJobs`, `useBackupRuns`, `useBackupAlerts` gain `serviceId` in `queryKey`. `useBackupDashboard` **unchanged** (PI-105, PI-106).
- `api/client.ts` + `api/backups.ts` — 6 fetch fns gain optional `serviceId``?service_id=` via the shared `get(path, params)` helper. `fetchBackupDashboard` **NOT touched** (PI-108, PI-109).
- `pages/service-tabs/AlertsTab.tsx`, `MetricsTab.tsx`, `JobsTab.tsx` — call hooks with `instance.id`; the prior TODO comments about global scoping removed (PI-113..PI-115). The instance switcher on ServicePage naturally re-scopes: `instance.id` changes → `queryKey` changes → React Query refetches.
- Tests: `useBackups.test.ts` (+85) covers queryKey isolation + serviceId threading; `AlertsTab.test.tsx` updated for the instance.id wiring.
## Deviations from tasks.md / design
- None functional. `fetchBackupDashboard` / `useBackupDashboard` / `get_backup_dashboard` deliberately untouched (design decision 5, PI-117 preserved).
## Final gate results
| Gate | Result |
|---|---|
| `backend && PYTHONPATH=src python3 -m pytest -q` | **368 passed** (+6 new), 2 warnings (pre-existing pythonjsonlogger) |
| `backend && PYTHONPATH=src python3 -m ruff check src tests` | **All checks passed** |
| `frontend && npm run build` | **exit 0** (pre-existing chunk-size warning) |
| `frontend && npm run lint` | **0 errors**, 1 pre-existing warning (`WidgetConfigDialog.tsx`, untouched) |
| `frontend && npx vitest run` | **165 passed** (+7 new) |
## Verification
See `verify-report.md` — adversarial fresh-context review: **21/21 PASS**, all gates green. No blocking code findings. Archive blocker is doc-only (this file + ticked tasks clear it). Non-blocking: weak queryKey-isolation assertion in `useBackups.test.ts` (wiring correct in source; test could assert actual cache keys — LOW).