docs(03-01): complete admin API endpoints plan
- 03-01-SUMMARY.md: requireAdminEmail middleware + four admin endpoints - STATE.md: decisions, session continuity updated - ROADMAP.md: phase 3 progress updated - REQUIREMENTS.md: INFR-02, HLTH-01 marked complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ Requirements for initial release. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### Service Health
|
### Service Health
|
||||||
|
|
||||||
- [ ] **HLTH-01**: Admin can view live health status (healthy/degraded/down) for Document AI, Claude/OpenAI, Supabase, and Firebase Auth
|
- [x] **HLTH-01**: Admin can view live health status (healthy/degraded/down) for Document AI, Claude/OpenAI, Supabase, and Firebase Auth
|
||||||
- [x] **HLTH-02**: Each health probe makes a real authenticated API call, not just config checks
|
- [x] **HLTH-02**: Each health probe makes a real authenticated API call, not just config checks
|
||||||
- [x] **HLTH-03**: Health probes run on a scheduled interval, separate from document processing
|
- [x] **HLTH-03**: Health probes run on a scheduled interval, separate from document processing
|
||||||
- [x] **HLTH-04**: Health probe results persist to Supabase (survive cold starts)
|
- [x] **HLTH-04**: Health probe results persist to Supabase (survive cold starts)
|
||||||
@@ -30,7 +30,7 @@ Requirements for initial release. Each maps to roadmap phases.
|
|||||||
### Infrastructure
|
### Infrastructure
|
||||||
|
|
||||||
- [x] **INFR-01**: Database migrations create service_health_checks and alert_events tables with indexes on created_at
|
- [x] **INFR-01**: Database migrations create service_health_checks and alert_events tables with indexes on created_at
|
||||||
- [ ] **INFR-02**: Admin API routes protected by Firebase Auth with admin email check
|
- [x] **INFR-02**: Admin API routes protected by Firebase Auth with admin email check
|
||||||
- [x] **INFR-03**: 30-day rolling data retention cleanup runs on schedule
|
- [x] **INFR-03**: 30-day rolling data retention cleanup runs on schedule
|
||||||
- [x] **INFR-04**: Analytics writes use existing Supabase connection, no new database infrastructure
|
- [x] **INFR-04**: Analytics writes use existing Supabase connection, no new database infrastructure
|
||||||
|
|
||||||
@@ -86,8 +86,8 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| ANLY-01 | Phase 2 | Complete |
|
| ANLY-01 | Phase 2 | Complete |
|
||||||
| ANLY-03 | Phase 2 | Complete |
|
| ANLY-03 | Phase 2 | Complete |
|
||||||
| INFR-03 | Phase 2 | Complete |
|
| INFR-03 | Phase 2 | Complete |
|
||||||
| INFR-02 | Phase 3 | Pending |
|
| INFR-02 | Phase 3 | Complete |
|
||||||
| HLTH-01 | Phase 3 | Pending |
|
| HLTH-01 | Phase 3 | Complete |
|
||||||
| ANLY-02 | Phase 3 | Complete |
|
| ANLY-02 | Phase 3 | Complete |
|
||||||
| ALRT-03 | Phase 4 | Pending |
|
| ALRT-03 | Phase 4 | Pending |
|
||||||
|
|
||||||
|
|||||||
@@ -84,5 +84,5 @@ None yet.
|
|||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-02-24
|
Last session: 2026-02-24
|
||||||
Stopped at: Completed 03-02-PLAN.md — analytics instrumentation in processJob() at upload_started, completed, and failed lifecycle points.
|
Stopped at: Completed 03-01-PLAN.md — admin API endpoints (GET /health, GET /analytics, GET /alerts, POST /alerts/:id/acknowledge) with requireAdminEmail middleware.
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
115
.planning/phases/03-api-layer/03-01-SUMMARY.md
Normal file
115
.planning/phases/03-api-layer/03-01-SUMMARY.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
phase: 03-api-layer
|
||||||
|
plan: 01
|
||||||
|
subsystem: api
|
||||||
|
tags: [express, firebase-auth, typescript, postgres, admin-routes]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires:
|
||||||
|
- phase: 02-backend-services
|
||||||
|
provides: HealthCheckModel.findLatestByService, AlertEventModel.findActive/acknowledge, document_processing_events table
|
||||||
|
- phase: 01-data-foundation
|
||||||
|
provides: service_health_checks, alert_events, document_processing_events tables and models
|
||||||
|
provides:
|
||||||
|
- requireAdminEmail middleware (404 for non-admin, next() for admin)
|
||||||
|
- getAnalyticsSummary() aggregate query function with configurable time range
|
||||||
|
- GET /admin/health — latest health check for all four monitored services
|
||||||
|
- GET /admin/analytics — processing summary with uploads/success/failure/avg-time
|
||||||
|
- GET /admin/alerts — active alert events
|
||||||
|
- POST /admin/alerts/:id/acknowledge — mark alert acknowledged
|
||||||
|
affects:
|
||||||
|
- 04-frontend: consumes all four admin endpoints for admin dashboard
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- Admin routes use router-level middleware chain (addCorrelationId + verifyFirebaseToken + requireAdminEmail)
|
||||||
|
- requireAdminEmail reads env vars inside function body (Firebase Secrets timing)
|
||||||
|
- Fail-closed pattern: if no admin email configured, deny all with logged warning
|
||||||
|
- getPostgresPool() for aggregate SQL (Supabase JS client does not support COUNT/AVG)
|
||||||
|
- PostgreSQL parameterized interval with $1::interval explicit cast
|
||||||
|
- Response envelope { success, data, correlationId } on all admin endpoints
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- backend/src/middleware/requireAdmin.ts
|
||||||
|
- backend/src/routes/admin.ts
|
||||||
|
modified:
|
||||||
|
- backend/src/services/analyticsService.ts
|
||||||
|
- backend/src/index.ts
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "requireAdminEmail returns 404 (not 403) for non-admin users — does not reveal admin routes exist"
|
||||||
|
- "Env vars read inside function body, not module level — Firebase Secrets not available at module load time"
|
||||||
|
- "getPostgresPool() used for aggregate SQL (COUNT/AVG) — Supabase JS client does not support these operations"
|
||||||
|
- "Service names in health endpoint hardcoded to match healthProbeService: document_ai, llm_api, supabase, firebase_auth"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Admin auth chain: addCorrelationId → verifyFirebaseToken → requireAdminEmail (router-level, applied once)"
|
||||||
|
- "Admin 404 pattern: non-admin users and unconfigured admin get 404 to obscure admin surface"
|
||||||
|
|
||||||
|
requirements-completed: [INFR-02, HLTH-01, ANLY-02]
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 8min
|
||||||
|
completed: 2026-02-24
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 3 Plan 01: Admin API Endpoints Summary
|
||||||
|
|
||||||
|
**Four Firebase-auth-protected admin endpoints exposing health status, alert management, and processing analytics via requireAdminEmail middleware returning 404 for non-admin**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 8 min
|
||||||
|
- **Started:** 2026-02-24T05:03:00Z
|
||||||
|
- **Completed:** 2026-02-24T05:11:00Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 4
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
- requireAdminEmail middleware correctly fails closed (404) for non-admin users and unconfigured environments
|
||||||
|
- getAnalyticsSummary() uses getPostgresPool() for aggregate SQL with parameterized interval cast
|
||||||
|
- All four admin endpoints mounted at /admin with router-level auth chain
|
||||||
|
- TypeScript compiles without errors across the entire backend
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Create requireAdmin middleware and getAnalyticsSummary function** - `301d0bf` (feat)
|
||||||
|
2. **Task 2: Create admin routes and mount in Express app** - `4169a37` (feat)
|
||||||
|
|
||||||
|
**Plan metadata:** (docs commit pending)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
- `backend/src/middleware/requireAdmin.ts` - Admin email check middleware returning 404 for non-admin
|
||||||
|
- `backend/src/routes/admin.ts` - Admin router with health, analytics, alerts endpoints (4 handlers)
|
||||||
|
- `backend/src/services/analyticsService.ts` - Added AnalyticsSummary interface and getAnalyticsSummary()
|
||||||
|
- `backend/src/index.ts` - Added adminRoutes import and app.use('/admin', adminRoutes) mount
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
- requireAdminEmail returns 404 (not 403) — per locked decision, do not reveal admin routes exist
|
||||||
|
- Env vars read inside function body, not at module level — Firebase Secrets timing constraint (matches alertService.ts pattern)
|
||||||
|
- getPostgresPool() for aggregate SQL because Supabase JS client does not support COUNT/AVG filters
|
||||||
|
- Service names ['document_ai', 'llm_api', 'supabase', 'firebase_auth'] hardcoded to match healthProbeService output exactly
|
||||||
|
|
||||||
|
## 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 four admin endpoints are ready for Phase 4 (frontend) consumption
|
||||||
|
- Admin dashboard can call GET /admin/health, GET /admin/analytics, GET /admin/alerts, POST /admin/alerts/:id/acknowledge
|
||||||
|
- No blockers — TypeScript clean, response envelopes consistent with codebase patterns
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 03-api-layer*
|
||||||
|
*Completed: 2026-02-24*
|
||||||
Reference in New Issue
Block a user