diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 45c249a..5df04ac 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -31,10 +31,10 @@ ### API -- [ ] **API-01**: GET `/api/tenants/{tid}/devices/{did}/config-history` returns change timeline +- [x] **API-01**: GET `/api/tenants/{tid}/devices/{did}/config-history` returns change timeline - [ ] **API-02**: GET `/api/tenants/{tid}/devices/{did}/config/{snapshot_id}` returns full snapshot - [ ] **API-03**: GET `/api/tenants/{tid}/devices/{did}/config/{snapshot_id}/diff` returns unified diff -- [ ] **API-04**: RBAC enforced: operator+ can trigger backups, viewers can read history +- [x] **API-04**: RBAC enforced: operator+ can trigger backups, viewers can read history ### Frontend @@ -83,10 +83,10 @@ | DIFF-02 | Phase 5: Diff Engine | Complete | | DIFF-03 | Phase 5: Diff Engine | Complete | | DIFF-04 | Phase 5: Diff Engine | Complete | -| API-01 | Phase 6: History API | Pending | +| API-01 | Phase 6: History API | Complete | | API-02 | Phase 6: History API | Pending | | API-03 | Phase 6: History API | Pending | -| API-04 | Phase 6: History API | Pending | +| API-04 | Phase 6: History API | Complete | | UI-01 | Phase 7: Config History UI | Pending | | UI-02 | Phase 7: Config History UI | Pending | | UI-03 | Phase 8: Diff Viewer & Download | Pending | diff --git a/.planning/STATE.md b/.planning/STATE.md index 86e0c13..3257ead 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,16 +2,16 @@ gsd_state_version: 1.0 milestone: v9.6 milestone_name: milestone -status: completed -stopped_at: Completed 05-02-PLAN.md -last_updated: "2026-03-13T03:37:57.863Z" -last_activity: 2026-03-13 -- Completed 05-01 config diff service with TDD +status: in-progress +stopped_at: Completed 06-01-PLAN.md +last_updated: "2026-03-13T04:00:32.171Z" +last_activity: 2026-03-13 -- Completed 06-01 config history timeline endpoint progress: total_phases: 10 completed_phases: 5 - total_plans: 7 - completed_plans: 7 - percent: 86 + total_plans: 9 + completed_plans: 8 + percent: 89 --- # Project State @@ -21,16 +21,16 @@ progress: See: .planning/PROJECT.md (updated 2026-03-12) **Core value:** Operators can see exactly what changed on a router and when, with reliable config snapshots for download -**Current focus:** Phase 5: Diff Engine -- COMPLETE +**Current focus:** Phase 6: History API ## Current Position -Phase: 5 of 10 (Diff Engine) -- COMPLETE -Plan: 2 of 2 in current phase (05-02 complete) -Status: Phase 5 complete -Last activity: 2026-03-13 -- Completed 05-02 structured change parser with TDD +Phase: 6 of 10 (History API) +Plan: 1 of 2 in current phase (06-01 complete) +Status: In progress +Last activity: 2026-03-13 -- Completed 06-01 config history timeline endpoint -Progress: [█████████░] 86% +Progress: [█████████░] 89% ## Performance Metrics @@ -55,6 +55,7 @@ Progress: [█████████░] 86% *Updated after each plan completion* | Phase 05 P01 | 3min | 2 tasks | 4 files | | Phase 05 P02 | 2min | 2 tasks | 4 files | +| Phase 06 P01 | 2min | 2 tasks | 4 files | ## Accumulated Context @@ -80,6 +81,8 @@ Recent decisions affecting current work: - [Phase 05]: Diff service instantiates own OpenBaoTransitService per-call with close() for clean lifecycle - [Phase 05]: RETURNING id on snapshot INSERT to capture new_snapshot_id without separate query - [Phase 05]: Change parser is pure function; DB writes in diff service. RETURNING id on diff INSERT for linking. +- [Phase 06]: Raw SQL text() JOIN for timeline queries, consistent with config_diff_service pattern +- [Phase 06]: Pagination defaults limit=50, offset=0 with FastAPI Query validation (ge=1, le=200) ### Pending Todos @@ -91,6 +94,6 @@ None yet. ## Session Continuity -Last session: 2026-03-13T03:37:57.861Z -Stopped at: Completed 05-02-PLAN.md +Last session: 2026-03-13T04:00:00Z +Stopped at: Completed 06-01-PLAN.md Resume file: None diff --git a/.planning/phases/06-history-api/06-01-SUMMARY.md b/.planning/phases/06-history-api/06-01-SUMMARY.md new file mode 100644 index 0000000..4fedf1a --- /dev/null +++ b/.planning/phases/06-history-api/06-01-SUMMARY.md @@ -0,0 +1,95 @@ +--- +phase: 06-history-api +plan: 01 +subsystem: api +tags: [fastapi, sqlalchemy, pagination, timeline, rbac] + +# Dependency graph +requires: + - phase: 05-diff-engine + provides: router_config_changes and router_config_diffs tables with parsed change data +provides: + - GET /api/tenants/{tid}/devices/{did}/config-history endpoint + - get_config_history service function with pagination +affects: [06-02, frontend-config-history] + +# Tech tracking +tech-stack: + added: [] + patterns: [raw SQL text() joins for timeline queries, same RBAC pattern as config_backups] + +key-files: + created: + - backend/app/services/config_history_service.py + - backend/app/routers/config_history.py + - backend/tests/test_config_history_service.py + modified: + - backend/app/main.py + +key-decisions: + - "Raw SQL text() for JOIN query consistent with config_diff_service.py pattern" + - "Pagination defaults: limit=50, offset=0 with validation (ge=1, le=200 for limit)" + +patterns-established: + - "Config history queries use JOIN between changes and diffs tables for timeline view" + +requirements-completed: [API-01, API-04] + +# Metrics +duration: 2min +completed: 2026-03-13 +--- + +# Phase 6 Plan 1: Config History Timeline Summary + +**GET /config-history endpoint returning paginated change timeline with component, summary, timestamp, and diff metadata via JOIN query** + +## Performance + +- **Duration:** 2 min +- **Started:** 2026-03-13T03:58:03Z +- **Completed:** 2026-03-13T04:00:00Z +- **Tasks:** 2 +- **Files modified:** 4 + +## Accomplishments +- Config history service querying router_config_changes JOIN router_config_diffs for timeline entries +- REST endpoint with viewer+ RBAC and config:read scope enforcement +- 4 unit tests covering formatting, empty results, pagination, and ordering +- Router registered in main.py alongside existing config routers + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Config history service and tests (TDD)** - `f7d5aec` (feat) +2. **Task 2: Config history router and main.py registration** - `5c56344` (feat) + +## Files Created/Modified +- `backend/app/services/config_history_service.py` - Query function for paginated config change timeline +- `backend/app/routers/config_history.py` - REST endpoint with RBAC, pagination query params +- `backend/tests/test_config_history_service.py` - 4 unit tests with AsyncMock sessions +- `backend/app/main.py` - Router import and registration + +## Decisions Made +- Used raw SQL text() for the JOIN query, consistent with config_diff_service.py pattern +- Pagination limit constrained to 1-200 via FastAPI Query validation +- Copied _check_tenant_access helper (same pattern as config_backups.py) + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered +None + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- Config history timeline endpoint ready for frontend consumption +- Plan 06-02 can build on this for detailed diff view endpoints + +--- +*Phase: 06-history-api* +*Completed: 2026-03-13*