diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md new file mode 100644 index 0000000..2325b87 --- /dev/null +++ b/.planning/REQUIREMENTS.md @@ -0,0 +1,124 @@ +# Requirements: DiunDashboard + +**Defined:** 2026-03-23 +**Core Value:** Reliable, persistent visibility into which services need updating — data never disappears, and the dashboard is the one place you trust to show the full picture. + +## v1 Requirements + +Requirements for this milestone. Each maps to roadmap phases. + +### Data Integrity + +- [ ] **DATA-01**: Webhook events use proper UPSERT (ON CONFLICT DO UPDATE) instead of INSERT OR REPLACE, preserving tag assignments when an image receives a new event +- [ ] **DATA-02**: SQLite foreign key enforcement is enabled (PRAGMA foreign_keys = ON) so tag deletion properly cascades to tag assignments +- [ ] **DATA-03**: Webhook and API endpoints enforce request body size limits (e.g., 1MB) to prevent OOM from oversized payloads +- [ ] **DATA-04**: Test error handling uses t.Fatal instead of silent returns, so test failures are never swallowed + +### Backend Refactor + +- [ ] **REFAC-01**: Database operations are behind a Store interface with separate SQLite and PostgreSQL implementations +- [ ] **REFAC-02**: Package-level global state (db, mu, webhookSecret) is replaced with a Server struct that holds dependencies +- [ ] **REFAC-03**: Schema migrations use golang-migrate with separate migration directories per dialect (sqlite/, postgres/) + +### Database + +- [ ] **DB-01**: PostgreSQL is supported as an alternative to SQLite via pgx v5 driver +- [ ] **DB-02**: Database backend is selected via DATABASE_URL env var (present = PostgreSQL, absent = SQLite with DB_PATH) +- [ ] **DB-03**: Existing SQLite users can upgrade without data loss (baseline migration represents current schema) + +### Bulk Actions + +- [ ] **BULK-01**: User can acknowledge all pending updates at once with a single action +- [ ] **BULK-02**: User can acknowledge all pending updates within a specific tag/group + +### Search & Filter + +- [ ] **SRCH-01**: User can search updates by image name (text search) +- [ ] **SRCH-02**: User can filter updates by status (pending vs acknowledged) +- [ ] **SRCH-03**: User can filter updates by tag/group +- [ ] **SRCH-04**: User can sort updates by date, image name, or registry + +### Update Indicators + +- [ ] **INDIC-01**: Dashboard shows a badge/counter of pending (unacknowledged) updates +- [ ] **INDIC-02**: Browser tab title includes pending update count (e.g., "DiunDash (3)") +- [ ] **INDIC-03**: In-page toast notification appears when new updates arrive during polling +- [ ] **INDIC-04**: Updates that arrived since the user's last visit are visually highlighted + +### Accessibility & Theme + +- [ ] **A11Y-01**: Light/dark theme toggle with system preference detection (prefers-color-scheme) +- [ ] **A11Y-02**: Drag handle for tag reordering is always visible (not hover-only) + +## v2 Requirements + +Deferred to future milestone. Tracked but not in current roadmap. + +### Auto-Grouping + +- **GROUP-01**: Images are automatically grouped by Docker stack/compose project +- **GROUP-02**: Auto-grouping source is configurable (Docker socket, DIUN metadata, manual) + +### DIUN Integration + +- **DIUN-01**: DIUN and dashboard deploy as a single stack +- **DIUN-02**: Visual UI for managing DIUN notification channels +- **DIUN-03**: Visual UI for managing DIUN watched images + +### Additional UX + +- **UX-01**: Data retention with configurable TTL for acknowledged entries +- **UX-02**: Alternative tag assignment via dropdown (non-drag method) +- **UX-03**: Keyboard shortcuts for common actions +- **UX-04**: Browser notification API for background tab alerts +- **UX-05**: Filter by registry + +## Out of Scope + +| Feature | Reason | +|---------|--------| +| Auto-triggering image pulls or container restarts | Dashboard is a viewer, not an orchestrator; Docker socket access is a security risk | +| Notification channel management UI | DIUN already handles this; duplicating creates config drift | +| OAuth / multi-user accounts | Single-user self-hosted tool; reverse proxy auth is sufficient | +| Real-time WebSocket / SSE | 5s polling is adequate for low-frequency update signals | +| Mobile-native / PWA | Responsive web design is sufficient for internal tool | +| Changelog or CVE lookups per image | Requires external API integrations; different product scope | +| Undo for dismiss actions | Next DIUN scan recovers dismissed items; state complexity not justified | + +## Traceability + +Which phases cover which requirements. Updated during roadmap creation. + +| Requirement | Phase | Status | +|-------------|-------|--------| +| DATA-01 | — | Pending | +| DATA-02 | — | Pending | +| DATA-03 | — | Pending | +| DATA-04 | — | Pending | +| REFAC-01 | — | Pending | +| REFAC-02 | — | Pending | +| REFAC-03 | — | Pending | +| DB-01 | — | Pending | +| DB-02 | — | Pending | +| DB-03 | — | Pending | +| BULK-01 | — | Pending | +| BULK-02 | — | Pending | +| SRCH-01 | — | Pending | +| SRCH-02 | — | Pending | +| SRCH-03 | — | Pending | +| SRCH-04 | — | Pending | +| INDIC-01 | — | Pending | +| INDIC-02 | — | Pending | +| INDIC-03 | — | Pending | +| INDIC-04 | — | Pending | +| A11Y-01 | — | Pending | +| A11Y-02 | — | Pending | + +**Coverage:** +- v1 requirements: 22 total +- Mapped to phases: 0 +- Unmapped: 22 ⚠️ + +--- +*Requirements defined: 2026-03-23* +*Last updated: 2026-03-23 after initial definition*