docs(06-02): complete snapshot view and diff retrieval plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-12 23:04:48 -05:00
parent af7007df13
commit e8bf994e7d
4 changed files with 117 additions and 19 deletions

View File

@@ -32,8 +32,8 @@
### API
- [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
- [x] **API-02**: GET `/api/tenants/{tid}/devices/{did}/config/{snapshot_id}` returns full snapshot
- [x] **API-03**: GET `/api/tenants/{tid}/devices/{did}/config/{snapshot_id}/diff` returns unified diff
- [x] **API-04**: RBAC enforced: operator+ can trigger backups, viewers can read history
### Frontend
@@ -84,8 +84,8 @@
| DIFF-03 | Phase 5: Diff Engine | Complete |
| DIFF-04 | Phase 5: Diff Engine | Complete |
| API-01 | Phase 6: History API | Complete |
| API-02 | Phase 6: History API | Pending |
| API-03 | Phase 6: History API | Pending |
| API-02 | Phase 6: History API | Complete |
| API-03 | Phase 6: History API | Complete |
| API-04 | Phase 6: History API | Complete |
| UI-01 | Phase 7: Config History UI | Pending |
| UI-02 | Phase 7: Config History UI | Pending |

View File

@@ -17,7 +17,7 @@ Decimal phases appear between their surrounding integers in numeric order.
- [ ] **Phase 3: Snapshot Ingestion** - Backend NATS subscriber stores snapshots with SHA256 deduplication
- [x] **Phase 4: Manual Backup Trigger** - API endpoint for on-demand config backup via poller (completed 2026-03-13)
- [x] **Phase 5: Diff Engine** - Unified diff generation and structured change parsing (completed 2026-03-13)
- [ ] **Phase 6: History API** - REST endpoints for timeline, snapshot view, and diff retrieval with RBAC
- [x] **Phase 6: History API** - REST endpoints for timeline, snapshot view, and diff retrieval with RBAC (completed 2026-03-13)
- [ ] **Phase 7: Config History UI** - Timeline section on device page with change summaries
- [ ] **Phase 8: Diff Viewer & Download** - Unified diff display with syntax highlighting and .rsc download
- [ ] **Phase 9: Retention & Cleanup** - 90-day retention policy with automatic snapshot deletion
@@ -179,7 +179,7 @@ Note: Phase 9 depends only on Phase 3 and Phase 10 depends on Phases 3/4/5, so P
| 3. Snapshot Ingestion | 0/1 | Not started | - |
| 4. Manual Backup Trigger | 1/1 | Complete | 2026-03-13 |
| 5. Diff Engine | 2/2 | Complete | 2026-03-13 |
| 6. History API | 0/2 | Not started | - |
| 6. History API | 2/2 | Complete | 2026-03-13 |
| 7. Config History UI | 0/1 | Not started | - |
| 8. Diff Viewer & Download | 0/2 | Not started | - |
| 9. Retention & Cleanup | 0/1 | Not started | - |

View File

@@ -2,16 +2,16 @@
gsd_state_version: 1.0
milestone: v9.6
milestone_name: milestone
status: in-progress
stopped_at: Completed 06-01-PLAN.md
last_updated: "2026-03-13T04:00:32.171Z"
status: executing
stopped_at: Completed 06-02-PLAN.md
last_updated: "2026-03-13T04:04:21.853Z"
last_activity: 2026-03-13 -- Completed 06-01 config history timeline endpoint
progress:
total_phases: 10
completed_phases: 5
completed_phases: 6
total_plans: 9
completed_plans: 8
percent: 89
completed_plans: 9
percent: 100
---
# Project State
@@ -25,12 +25,12 @@ See: .planning/PROJECT.md (updated 2026-03-12)
## Current Position
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
Phase: 6 of 10 (History API) -- COMPLETE
Plan: 2 of 2 in current phase (all complete)
Status: Phase 6 complete
Last activity: 2026-03-13 -- Completed 06-02 snapshot view and diff retrieval endpoints
Progress: [█████████] 89%
Progress: [█████████] 100%
## Performance Metrics
@@ -56,6 +56,7 @@ Progress: [█████████░] 89%
| Phase 05 P01 | 3min | 2 tasks | 4 files |
| Phase 05 P02 | 2min | 2 tasks | 4 files |
| Phase 06 P01 | 2min | 2 tasks | 4 files |
| Phase 06 P02 | 2min | 2 tasks | 3 files |
## Accumulated Context
@@ -83,6 +84,8 @@ Recent decisions affecting current work:
- [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)
- [Phase 06]: Transit decrypt in get_snapshot with try/finally for clean openbao lifecycle
- [Phase 06]: 500 error wrapping for Transit decrypt failures in router layer, not service
### Pending Todos
@@ -94,6 +97,6 @@ None yet.
## Session Continuity
Last session: 2026-03-13T04:00:00Z
Stopped at: Completed 06-01-PLAN.md
Last session: 2026-03-13T04:04:21.850Z
Stopped at: Completed 06-02-PLAN.md
Resume file: None

View File

@@ -0,0 +1,95 @@
---
phase: 06-history-api
plan: 02
subsystem: api
tags: [fastapi, sqlalchemy, openbao, transit-decrypt, rbac, snapshot]
# Dependency graph
requires:
- phase: 06-history-api
provides: config_history_service.py with get_config_history, config_history router with RBAC
- phase: 05-diff-engine
provides: router_config_diffs and router_config_snapshots tables with encrypted config data
provides:
- GET /api/tenants/{tid}/devices/{did}/config/{snapshot_id} endpoint (decrypted snapshot)
- GET /api/tenants/{tid}/devices/{did}/config/{snapshot_id}/diff endpoint (unified diff)
- get_snapshot and get_snapshot_diff service functions
affects: [frontend-config-history, frontend-diff-viewer]
# Tech tracking
tech-stack:
added: []
patterns: [Transit decrypt in service layer with try/finally close, 404 for missing snapshots/diffs]
key-files:
created: []
modified:
- backend/app/services/config_history_service.py
- backend/app/routers/config_history.py
- backend/tests/test_config_history_service.py
key-decisions:
- "Transit decrypt in get_snapshot with try/finally for clean openbao lifecycle"
- "500 error wrapping for Transit decrypt failures in router (not service)"
patterns-established:
- "Snapshot retrieval filters by id + device_id + tenant_id for RLS-safe queries"
requirements-completed: [API-02, API-03, API-04]
# Metrics
duration: 2min
completed: 2026-03-13
---
# Phase 6 Plan 2: Snapshot View and Diff Retrieval Summary
**Snapshot view and diff retrieval endpoints with Transit decrypt for full config text and unified diff, enforcing viewer+ RBAC**
## Performance
- **Duration:** 2 min
- **Started:** 2026-03-13T04:01:58Z
- **Completed:** 2026-03-13T04:03:39Z
- **Tasks:** 2
- **Files modified:** 3
## Accomplishments
- get_snapshot function decrypts config via OpenBao Transit and returns plaintext with metadata
- get_snapshot_diff function queries diff by new_snapshot_id for a device/tenant
- Two new router endpoints with viewer+ RBAC and config:read scope enforcement
- 4 new tests (8 total) covering decrypted content, not-found, diff retrieval, and no-diff cases
## Task Commits
Each task was committed atomically:
1. **Task 1: Snapshot and diff service functions with tests (TDD)** - `83cd661` (feat)
2. **Task 2: Snapshot and diff router endpoints** - `af7007d` (feat)
## Files Created/Modified
- `backend/app/services/config_history_service.py` - Added get_snapshot (Transit decrypt) and get_snapshot_diff query functions
- `backend/app/routers/config_history.py` - Two new GET endpoints with RBAC, 404/500 error handling
- `backend/tests/test_config_history_service.py` - 4 new tests with mocked Transit and DB sessions
## Decisions Made
- Transit decrypt happens in service layer (get_snapshot), error wrapping in router layer (500 response)
- Query filters include device_id + tenant_id alongside snapshot_id for RLS-safe access
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- All 3 config history API endpoints complete (timeline, snapshot view, diff view)
- Phase 06 complete -- ready for frontend integration
---
*Phase: 06-history-api*
*Completed: 2026-03-13*