diff --git a/.gitignore b/.gitignore index 0799d76..942ef05 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,9 @@ target/ .idea custom-bullshit +*.db +*.sqlite +*.sqlite3 # User-specific stuff .idea/**/workspace.xml diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..669aa71 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,288 @@ +# Owlibou Tavern — Detailed Roadmap (M0 → M10) + +A focused plan for Dioxus Fullstack (Workspace Edition 2024), admin/editor CRUD, private deployment, legal sensitivity, and SQLx ergonomics. + +--- + +## M0 — Workspace Bootstrap (Dioxus Fullstack WSE 2024) +**Goal:** Reproducible workspace skeleton with SSR + client, ready for DB + auth. + +**Deliverables** +- `rust-toolchain.toml` pinned to `RUST_STABLE` +- Cargo **workspace** with crates: + - `app-web` (Dioxus Web) + - `app-server` (Axum/Dioxus server functions + SSR) + - `domain` (entities, DTOs, validators, error types) + - `data` (DB pool, queries, migrations wrapper) + - `shared` (isomorphic types/formatters for web+server) + - `cli` (admin ops: create admin user, run migrations, seed) +- Dioxus config for Workspace Edition 2024 (server functions enabled) +- Tracing/logging, error boundary scaffold, `.env` loading + +**Key Steps** +1. **Workspace** + - Root `Cargo.toml` with members. + - `rust-toolchain.toml` with `channel = "RUST_STABLE"`. +2. **Server** + - Axum + Dioxus Fullstack integration (SSR, server functions). + - `tower-http` for compression, security headers, request logging. +3. **Web** + - Dioxus Router; app shell (sidebar/topbar); error boundary + 404 route. +4. **Common** + - `thiserror` + `anyhow` error model; `serde` for JSON. + - `tracing` + `tracing-subscriber` with `RUST_LOG`. +5. **DX** + - `dx` tasks or `cargo-watch` for hot reload. + - Pre-commit hooks: `cargo fmt --check`, `clippy -D warnings`. + +**Acceptance** +- `cargo run -p app-server` serves SSR page. +- Hot reload works; logs render; basic routes respond. + +**Assumptions challenged** +- Server functions vs. pure REST: if non-Dioxus clients likely, prefer REST now and use server functions selectively. + +--- + +## M1 — Data Layer & Migrations +**Goal:** Safe DB access layer; deterministic migrations; WAL & pragmas if SQLite. + +**Deliverables** +- `data` crate: pool factory, migrations runner, query helpers. +- `sqlx` wired; `.env` (`DATABASE_URL`), connection healthcheck. +- Migration files mirroring `/database/main`. + +**Key Steps** +1. Add `sqlx` + `sqlx-cli`; enable `sqlite` (or your DB) features. +2. `sqlx::migrate!()` (or CLI) to run migrations at startup/CLI. +3. Pool settings (max cons, timeouts); WAL mode if SQLite. +4. `domain` structs mirroring tables; `FromRow` derives; validators. + +**Acceptance** +- `cargo run -p cli migrate` applies migrations. +- `/healthz/db` returns OK. + +**Assumptions challenged** +- If schema evolves fast, add **idempotent** migrations and a **baseline**. + +--- + +## M2 — Read-Only DB Viewer (Browser) +**Goal:** Admin table browser with pagination, sort, filters, detail view. + +**Deliverables** +- Table list page (all tables) +- Grid view per table with server-side pagination +- Type-aware rendering (dates, bools, FKs as labels) +- Record detail drawer/view + +**Key Steps** +1. API/server functions: `GET /api/v1/{table}` w/ `page`, `q`, `order`. +2. UI: reusable ``; column config via schema reflection or static map. +3. Empty state, loading, error toasts. + +**Acceptance** +- Browse all tables; sort; filter; open details. + +**Counterpoint** +- Don’t overbuild a “universal admin” first—target priority tables. + +--- + +## M3 — CRUD for One Core Entity +**Goal:** End-to-end create/edit/delete for the flagship table. + +**Deliverables** +- Create/Edit forms with client + server validation +- Delete with confirm modal; optimistic UI update +- Consistent error model → field vs. form errors + +**Key Steps** +1. REST/server functions: `POST/PUT/DELETE /api/v1/entity`. +2. `validator` crate or bespoke validators in `domain`. +3. UI: form components (text, select, date, FK pickers); dirty-state guard. + +**Acceptance** +- Create/edit/delete works; bad input → friendly field errors. + +**Assumption challenged** +- Complex relations? Use a **form stepper** or “+ create related” in-place. + +--- + +## M4 — Authentication (Private Setup) +**Goal:** Session-based login, secure cookies, password hashing. + +**Deliverables** +- `/login`, `/logout`, `/me` +- Session middleware (cookies: HttpOnly, Secure, SameSite=Strict) +- `argon2` (or `bcrypt`) hashing; password policy checks +- Login page; lockout/backoff after N failures + +**Key Steps** +1. `axum-login` or `tower-sessions` + user store. +2. CSRF mitigation for cookie sessions (token or double-submit). +3. CLI to create first admin: `cli user create --admin`. + +**Acceptance** +- Only authenticated users can access viewer/CRUD. +- Brute-force throttling observable. + +**Skeptic note** +- Single-origin private admin → cookies > JWT for simplicity/safety. + +--- + +## M5 — RBAC & Policy Enforcement +**Goal:** Least-privilege access; backend **and** UI gating. + +**Deliverables** +- Roles: `Admin`, `Editor`, (optional `Viewer`) +- `AuthContext { user_id, roles }` extractor +- Route guards (e.g., only Admin can delete; Editor can create/update) +- UI hides forbidden actions; backend still enforces + +**Key Steps** +1. Permission matrix (routes × roles). +2. Axum layer/guards per route group. +3. Audit log table (`who`, `when`, `what`, `before→after`). + +**Acceptance** +- Forbidden ops → 403; writes are audited. + +**Bias flag** +- Hiding buttons ≠ authorization. Enforce on server. + +--- + +## M6 — Full Schema Coverage & Relations UX +**Goal:** CRUD across schema; ergonomic FK/M2M editing. + +**Deliverables** +- Per-table pages with consistent forms +- FK pickers with search (typeahead) and clear labels +- M2M editors (dual list, multi-select, or chips) +- Bulk actions (delete, export CSV) with permission checks + +**Key Steps** +1. Label resolution helpers (JOINs or cached lookups). +2. Server-side pagination for big tables; index review. +3. Import/export (CSV/JSON) with validation + dry-run. + +**Acceptance** +- Each table has list/detail/edit; relations feel smooth; import/export works. + +**Counterpoint** +- Extract a form generator only after repeating patterns emerge. + +--- + +## M7 — Security Hardening (Legal Sensitivity) +**Goal:** Tighten security; document threat model; minimize blast radius. + +**Deliverables** +- TLS via `rustls` **or** reverse proxy (Caddy/nginx) +- Strict CORS (or disabled), `Content-Security-Policy`, `Referrer-Policy` +- Input validation everywhere; no string-built SQL +- Secrets in env/secret store; none in git +- Data retention policy + purges +- Optional: field-level encryption at rest for sensitive columns + +**Key Steps** +1. Security headers middleware. +2. Rate limiting per session/IP for writes. +3. Structured logging; redact PII; access + write audit logs. +4. Backups & key rotation plan; restore rehearsal. + +**Acceptance** +- SSL Labs A (if exposed); scanners clean; restore drill passes. + +**Frame shift** +- Treat it as **regulated** even if it isn’t—cheaper than breach postmortems. + +--- + +## M8 — Ops: Build, Deploy, Backup +**Goal:** One-command build/deploy; predictable backups; health & metrics. + +**Deliverables** +- Multi-stage Dockerfile; `docker-compose.yml` for private stack +- Systemd unit (if bare-metal) with `Restart=always` +- Health endpoints `/healthz`, `/readyz`; DB readiness check +- Backups: nightly DB snapshot + off-host copy; retention window + +**Key Steps** +1. CI: build, test, produce image/artifacts. +2. Observability: basic metrics (req/s, p95), log shipper. +3. Runbook: deploy, rollback, rotate secrets, restore backup. + +**Acceptance** +- Fresh machine → deploy in minutes with docs; restore tested. + +**Counterpoint** +- LAN-only? A simple systemd service may beat Docker complexity. + +--- + +## M9 — Testing: Unit, Integration, E2E +**Goal:** Confidence without ceremony. + +**Deliverables** +- Unit tests: `domain` validators, `data` queries (test DB) +- Integration tests: APIs (ephemeral DB; hit endpoints) +- E2E smoke: Playwright (or similar) against SSR app + +**Key Steps** +1. Test fixtures: migrate temp DB, seed minimal data. +2. Golden tests for JSON; snapshot UI for critical pages. +3. Security tests: auth bypass, CSRF, rate limits. + +**Acceptance** +- CI runs and fails on regressions. + +--- + +## M10 — Docs & Admin UX Polish +**Goal:** Maintainable, pleasant, self-serve. + +**Deliverables** +- `README.md` (setup/run/deploy) + `SECURITY.md` + `RUNBOOK.md` +- Admin guide (user mgmt, imports, backups) +- QoL: keyboard shortcuts, column presets, saved filters + +**Acceptance** +- New teammate stands it up and performs CRUD in ≤30 minutes using docs. + +--- + +## Implementation Checklists + +**Pin toolchain & linting** +- `rust-toolchain.toml` → `channel="RUST_STABLE"` +- `.cargo/config.toml` tuned for dev +- `cargo fmt`, `clippy -D warnings` in CI + +**Security defaults** +- Cookies: `HttpOnly`, `Secure`, `SameSite=Strict` +- CSP: `default-src 'self'`; `frame-ancestors 'none'`; block mixed content +- No dev endpoints in prod; no directory listings +- DB: prepared statements only; least privilege + +**DB pragmas (SQLite)** +- WAL mode; `synchronous=NORMAL` (or `FULL` for extra safety) +- `PRAGMA foreign_keys = ON;` +- Indices for filters/sorts used in viewer + +--- + +## Risks & Mitigations +- **Generic admin scope creep.** Focus on 1–2 core entities (M3); templatize later. +- **Auth choice confusion.** Private, single-origin → cookies; avoid JWT complexity. +- **Log-based legal exposure.** Redact PII; isolate/audit logs; retention limits. +- **Backups untested.** Run restore drills. Untested backups are fiction. + +--- + +## Assumptions (call out for correction) +- Using **SQLx + SQLite** initially (swap easily for Postgres/MySQL). +- Private LAN/VPN deployment; not publicly exposed unless decided later. diff --git a/rules.db b/rules.db deleted file mode 100644 index 2dc68b4..0000000 Binary files a/rules.db and /dev/null differ diff --git a/rules.db.empty b/rules.db.empty deleted file mode 100644 index 2dc68b4..0000000 Binary files a/rules.db.empty and /dev/null differ