- Gate native Tokio/Axum main() with #[cfg(not(target_arch = "wasm32"))]
- Add #![cfg_attr(target_arch = "wasm32", no_main)] to suppress missing-main error
- Add #[worker::event(fetch)] entry point using worker::HttpRequest / http::Response<axum::body::Body>
- Enable `http` feature on worker dep so fetch handler uses standard http types
- Add axum (json+query features), tower-service, and http to wasm32 deps
- Move async-trait to shared [dependencies] so both targets have it
- Make db::d1 module pub so main.rs can access D1Repository on wasm32
- Fix worker::d1::Database → D1Database and PreparedStatement → D1PreparedStatement
- Add #[cfg_attr(target_arch = "wasm32", worker::send)] to all 7 handler fns
so their futures satisfy Axum's Handler<Send> bound on single-threaded wasm32
- Remove redundant #![cfg(target_arch="wasm32")] from d1.rs (module
declaration in mod.rs already gates it)
- Remove unused D1Repository re-export from db/mod.rs
- Drop unused page/total_count fields from UI ListResponse struct
(only total_pages is consumed by the browse page)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace all 7 stub methods in src/bin/api/db/d1.rs with full working
implementations using the Cloudflare D1 API from workers-rs 0.5.
Implements:
- run_migrations: executes four DDL statements via db.exec()
- list_quotes: dynamic WHERE clause with positional params, COUNT query,
paginated SELECT, per-quote tag fetch
- get_quote: prepared statement with first::<QuoteRow>()
- get_random_quote: ORDER BY RANDOM() LIMIT 1
- create_quote: INSERT + batch tag insert + read-back for timestamps
- update_quote: auth check, dynamic SET clause, optional tag replacement,
read-back of updated row
- delete_quote: auth check, DELETE, returns DeleteResult enum
Also adds helper structs (QuoteRow, AuthRow, TagRow, CountRow),
fetch_tags() helper method, and unsafe Send/Sync impls required for
Arc<dyn QuoteRepository + Send + Sync> on single-threaded wasm32.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Detect 404 from random quote endpoint and render a friendly
'Nothing here yet — Submit a quote!' message with a link to
/submit instead of the generic error display.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace 'Submit another' link with 'Browse all quotes' -> Route::Browse
- Change date input from type=text to type=date, remove placeholder
- Make author optional (defaults to Anonymous), update label
- Clarify auth code label to 'Edit/delete passphrase'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 26 integration tests in handlers::integration_tests using a real
NativeRepository backed by a NamedTempFile SQLite database. Each test
gets an isolated database via test_router(). tempfile added to
[dev-dependencies]. Closes tickets: 5f5ba0, 9b581f, 789d0f, aa0eab,
f9f448, 4a4c26, 93f1b6, fae330, 8c87db, 893eba, e8f5cf, ce1e4f.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- HomePage: fetches random quote on mount, displays with QuoteCard and browse/submit links
- BrowsePage: paginated list with author and tag filter inputs, Pagination component
- QuotePage: view/edit/delete with AuthModal gating, 403/404 handling, sessionStorage auth
- AuthorPage: lists quotes by author with tag filter and pagination
- SubmitPage: full form with all fields, success state showing auth code prominently
- Tag filter (d3d502) integrated into Browse and Author pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Create build.rs at crate root using serde_yaml (build-dep only) to parse
api/openapi.yaml and write compact JSON to $OUT_DIR/openapi.json
- cargo:rerun-if-changed ensures re-conversion only when spec changes
- serde_yaml never enters the Workers or native binary (build-dep only)
- Downstream GET /api/ handler consumes via include_str!(concat!(env!("OUT_DIR"), "/openapi.json"))
Closes ticket 8892d5
- Add yew 0.22 with csr feature for Rust/Wasm SPA frontend
- Add yew-router 0.19 for client-side routing
- Add gloo 0.11 for Web API utilities (timers, fetch, events)
- Add wasm-bindgen 0.2 matching Nix wasm-bindgen-cli 0.2.108
- Add wasm-bindgen-futures 0.4 for async fetch support
- Add web-sys 0.3 for raw DOM/browser API bindings
All UI deps scoped to wasm32 cfg target to avoid host build pollution
Closes ticket 93515e
- Add uuid = { version = "1", features = ["v4", "serde"] } to [dependencies]
- Add getrandom = { version = "0.4", features = ["wasm_js"] } under wasm32 cfg
- Implement generate_id() in src/lib.rs with rustdoc and doctest
- Add unit tests for length, hyphen count, and uniqueness
Closes ticket 7a0d9f
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the three separate sub-crates (api/, ui/, tests/) with a single
Cargo crate at the quotesdb/ root. Shared code lives in src/lib.rs; the
api and ui are multi-binary targets; integration tests use the standard
Cargo tests/ layout. Trunk files moved to project root with data-bin="ui".
Closes ticket b38032.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add working-directory rule to root and all project docs
- Generalize root from "HTTP web services" to "independent projects"
- Add @../CLAUDE.md inheritance to nbd, edu, quotesdb project docs
- Remove sections duplicated from root in project-level docs
- Wrap all sections in semantic XML tags for clearer agent parsing
- Rename Tech Stack → Common Patterns (framed as defaults, not requirements)
- Rename Running Services Locally → Running Projects Locally
Evaluated all quotesdb tickets and assigned each to the correct sub-project
dependency (api/f3dc74, ui/c3503b, qa/ce1e4f, infra/25c413). Also wired
inter-ticket dependencies to enforce correct implementation order within each
domain and cross-domain (e.g. QA test suites depend on the API handlers they
exercise). Validated with `nbd graph --json` — 78 nodes, 200 edges, no cycles.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds 84 tickets across 4 sub-domains with a full dependency graph:
- quotesdb/api (f3dc74): 15 work tickets + 6 TRIAGE tickets
Covers Cargo.toml, Workers entry point, DB migrations, all 7 endpoints,
auth code gen, tag handling, error envelope, unit tests, and docs.
- quotesdb/ui (c3503b): 15 work tickets + 5 TRIAGE tickets
Covers Yew/Wasm setup, Trunk config, app shell, API client, 5 pages,
shared components (QuoteCard, auth modal, pagination, tag filter), and docs.
- quotesdb/qa (ce1e4f): 12 work tickets + 4 TRIAGE tickets
Covers test harness, one test suite per endpoint, router ordering,
tag operations, and README.
- quotesdb/infra (25c413): 10 work tickets + 6 TRIAGE tickets
Covers OpenTofu setup, D1 database, Worker script + route, Pages project,
custom domain (quotes.elijah.run), migration workflow, secrets, and README.
Dependency graph:
- Root ticket (ec118c) blocked on all 4 sub-project tickets
- Sub-project tickets blocked on their leaf work tickets
- Work tickets have intra-domain sequential deps (e.g. Cargo.toml → DB → handlers)
- QA test harness has a cross-domain dep on the completed api sub-project
- All 21 TRIAGE tickets are immediately unblocked as the highest-priority starting work
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>