9.3 KiB
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 toRUST_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
- Workspace
- Root
Cargo.toml
with members. rust-toolchain.toml
withchannel = "RUST_STABLE"
.
- Root
- Server
- Axum + Dioxus Fullstack integration (SSR, server functions).
tower-http
for compression, security headers, request logging.
- Web
- Dioxus Router; app shell (sidebar/topbar); error boundary + 404 route.
- Common
thiserror
+anyhow
error model;serde
for JSON.tracing
+tracing-subscriber
withRUST_LOG
.
- DX
dx
tasks orcargo-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
- Add
sqlx
+sqlx-cli
; enablesqlite
(or your DB) features. sqlx::migrate!()
(or CLI) to run migrations at startup/CLI.- Pool settings (max cons, timeouts); WAL mode if SQLite.
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
- API/server functions:
GET /api/v1/{table}
w/page
,q
,order
. - UI: reusable
<DataGrid>
; column config via schema reflection or static map. - 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
- REST/server functions:
POST/PUT/DELETE /api/v1/entity
. validator
crate or bespoke validators indomain
.- 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
(orbcrypt
) hashing; password policy checks- Login page; lockout/backoff after N failures
Key Steps
axum-login
ortower-sessions
+ user store.- CSRF mitigation for cookie sessions (token or double-submit).
- 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
, (optionalViewer
) 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
- Permission matrix (routes × roles).
- Axum layer/guards per route group.
- 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
- Label resolution helpers (JOINs or cached lookups).
- Server-side pagination for big tables; index review.
- 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
- Security headers middleware.
- Rate limiting per session/IP for writes.
- Structured logging; redact PII; access + write audit logs.
- 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
- CI: build, test, produce image/artifacts.
- Observability: basic metrics (req/s, p95), log shipper.
- 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
- Test fixtures: migrate temp DB, seed minimal data.
- Golden tests for JSON; snapshot UI for critical pages.
- 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 devcargo 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
(orFULL
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.