Initial commit
This commit is contained in:
commit
38c24fc9dc
166 files changed
+22002
No files matched your search
@@ -0,0 +1,130 @@
|
||||
# 08 — Implementation Plan (Phases 2–10)
|
||||
|
||||
Each phase ends with: run tests, run lint, build, fix all errors, verify
|
||||
`docker compose up -d` still works end-to-end for whatever exists so far.
|
||||
No phase starts until the previous one is green.
|
||||
|
||||
## Phase 2 — Bootstrap project & Docker Compose
|
||||
|
||||
- npm/pnpm workspace scaffold (`apps/server`, `apps/web`, `packages/shared`)
|
||||
- Fastify skeleton with the two listeners (8080/8081), `/health`, `/ready`
|
||||
- Vite + React + Tailwind skeleton, dark theme tokens, empty shell page
|
||||
- Drizzle configured against Postgres; `docker-compose.yml` (dev) brings up
|
||||
`notizarr` (hot-reload) + `notizarr-postgres`
|
||||
- `Dockerfile` (multi-stage: build web → build server → copy web dist into
|
||||
server's static dir → slim runtime image), non-root user, healthcheck
|
||||
script
|
||||
- **Exit criteria:** `docker compose up -d` succeeds, `notizarr-postgres` is
|
||||
healthy, `GET :8080/health` returns 200, empty React shell loads.
|
||||
|
||||
## Phase 3 — Database + backend API skeleton
|
||||
|
||||
- All tables from `03-database-model.md` as Drizzle schema + migrations
|
||||
- CRUD-level modules for `topics`, `notifications` (insert, list, get) with
|
||||
no auth yet (stubbed), so the data layer can be exercised
|
||||
- OpenAPI schema generation wired up, `/docs` serving it
|
||||
- Unit tests for schema constraints (unique slugs, FK cascades, retention
|
||||
math)
|
||||
- **Exit criteria:** migrations run clean on a fresh DB; can insert/list a
|
||||
topic and a notification via the API without auth.
|
||||
|
||||
## Phase 4 — Authentication + API tokens
|
||||
|
||||
- OIDC module (`openid-client`): login/callback/logout, PKCE, state/nonce
|
||||
validation, session cookie issuance, bootstrap-first-admin logic
|
||||
- Proxy-auth module: trusted-CIDR check, header parsing, session creation
|
||||
- `AUTH_MODE=disabled` (local dev convenience: single implicit admin user)
|
||||
- API token module: create/list/revoke/rotate, hashing, scoping
|
||||
(topics/source/CIDR/expiry), last-used tracking
|
||||
- CSRF protection (Origin check + custom header) on listener A mutations
|
||||
- Tests: each auth mode, token scope enforcement, revoked/expired token
|
||||
rejection, CSRF rejection on cross-origin mutation attempts
|
||||
- **Exit criteria:** MVP criteria #5–7 (auth works, admin can create a
|
||||
topic, admin can create a scoped token) pass manually and via tests.
|
||||
|
||||
## Phase 5 — Notification ingestion + history
|
||||
|
||||
- Listener B: canonical publish endpoint, `/api/v1/topics/:slug` alias,
|
||||
ntfy-compat endpoint, webhook endpoint
|
||||
- Rate limiter (per-token, per-IP), `INGESTION_ALLOWED_CIDRS` enforcement
|
||||
- Deduplication logic, occurrence_count increment
|
||||
- SSE stream on listener A (`notification.created`/`updated` events)
|
||||
- Read/unread + starred state, unread-count aggregation per topic
|
||||
- Retention cleanup interval job
|
||||
- Tests: ingestion auth/scoping, rate limiting (burst + sustained), dedup
|
||||
window behavior, SSE fan-out, retention deletion
|
||||
- **Exit criteria:** MVP criteria #8–10 (LAN client can publish, appears
|
||||
instantly via SSE, persisted) pass.
|
||||
|
||||
## Phase 6 — Frontend UI
|
||||
|
||||
- Navigation shells: mobile bottom nav (Inbox/Topics/Search/Starred/
|
||||
Settings), desktop sidebar + stream + optional detail panel
|
||||
- Topic list (unread/total/latest, bell state), topic settings screen
|
||||
(push ON/OFF toggle)
|
||||
- Notification list (cards per spec), notification detail
|
||||
(`/topics/:slug/messages/:id`), search + filters
|
||||
- Empty states, loading skeletons, dark-first theme, responsive breakpoints
|
||||
- Manual + automated visual smoke checks in the Browser tool (mobile and
|
||||
desktop viewport)
|
||||
- **Exit criteria:** MVP criteria #22 (polished on iPhone and desktop) —
|
||||
judged by hand in the browser tool at this stage, refined further in
|
||||
Phase 7/8.
|
||||
|
||||
## Phase 7 — PWA + Web Push
|
||||
|
||||
- `vite-plugin-pwa` with `injectManifest`, manifest.webmanifest, icon set
|
||||
(incl. maskable + apple-touch-icon), safe-area CSS
|
||||
- Service worker: precache, runtime caching, `push`/`notificationclick`
|
||||
handlers
|
||||
- VAPID generation/storage in `system_settings`, `web-push` send integration
|
||||
wired into the Phase 5 fan-out step (previously a no-op stub)
|
||||
- Subscribe/unsubscribe flow, devices screen, diagnostics screen
|
||||
- Manual iPhone test pass (install to Home Screen, enable notifications,
|
||||
trigger a real push, confirm deep link opens the right message)
|
||||
- **Exit criteria:** MVP criteria #11–18 (PWA installable, push permission,
|
||||
subscription stored, push ON sends / OFF doesn't, arrives on iPhone,
|
||||
tapping opens exact notification) pass.
|
||||
|
||||
## Phase 8 — Admin UI + rate limiting polish + diagnostics
|
||||
|
||||
- Admin dashboard widgets (`04-api-design.md`'s `/admin/stats/dashboard`)
|
||||
- Noisy-source detection thresholds + admin warnings
|
||||
- Tokens/Users/Devices/Push/Security/System admin screens
|
||||
- Audit log viewer
|
||||
- Settings screens (user + admin) per `01-architecture.md`
|
||||
- **Exit criteria:** full admin IA from the spec is navigable and
|
||||
functional; rate-limit rejections are visible end-to-end (trigger one,
|
||||
see it flagged).
|
||||
|
||||
## Phase 9 — Migration helpers + ntfy compatibility hardening
|
||||
|
||||
- `docs/migration-ntfy.md`: side-by-side ntfy → Notizarr endpoint mapping
|
||||
- `docs/home-assistant.md`: `rest_command` example replacing `ntfy.publish`
|
||||
(as given in the spec), plus one example per currently-used service
|
||||
(Seerr, Uptime Kuma, generic webhook)
|
||||
- Compatibility test matrix: header-based, JSON-based, query-param-based
|
||||
ntfy-style requests all produce equivalent stored notifications
|
||||
- **Exit criteria:** MVP criteria #8 re-verified using an ntfy-style request
|
||||
shape, not just the canonical API.
|
||||
|
||||
## Phase 10 — Testing + hardening + documentation
|
||||
|
||||
- Fill any remaining gaps in the automated test list from the original spec
|
||||
(stale push subscription cleanup, device removal, authorization matrix
|
||||
across roles, retention cleanup edge cases)
|
||||
- Security pass: CSP, HSTS, frame-ancestors, request size limits, dependency
|
||||
audit
|
||||
- Top-level `README.md`: install, configure `.env`, deploy on Unraid,
|
||||
backup/restore, troubleshooting (linking the diagnostics screen)
|
||||
- Full MVP acceptance checklist run end-to-end, including container
|
||||
restart persistence checks (#19–21)
|
||||
- **Exit criteria:** all 22 MVP acceptance criteria pass.
|
||||
|
||||
## Cross-cutting, done incrementally rather than as a separate phase
|
||||
|
||||
- Structured logging + secret redaction: introduced in Phase 2, extended as
|
||||
new modules land
|
||||
- Metrics: introduced alongside the ingestion endpoints in Phase 5
|
||||
- Lint/typecheck/test/build as CI-equivalent local commands: set up in
|
||||
Phase 2, run at the end of every subsequent phase
|
||||
Reference in new issue
Block a user