chore(quotesdb): init nbd and create root project ticket
parent
955cf029ab
commit
05bad425a7
@ -0,0 +1,456 @@
|
||||
+++
|
||||
title = "quotesdb"
|
||||
priority = 8
|
||||
status = "todo"
|
||||
ticket_type = "project"
|
||||
dependencies = []
|
||||
+++
|
||||
# QuotesDB Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Bootstrap the `quotesdb` service (Rust/Axum backend on Cloudflare Workers + Yew frontend on Cloudflare Pages), then orchestrate parallel agents to plan and implement the work.
|
||||
|
||||
**Architecture:** Three-phase delivery: (0) design ✓, (1) 4 parallel planning agents ticket work in git worktrees, (2) 4 parallel implementation orchestrators dispatch sub-agents per ticket. Each subdomain (api, ui, tests, infra) lives in its own directory under `quotesdb/` as an independent Rust crate.
|
||||
|
||||
**Tech Stack:** Rust, Axum, Tokio, workers-rs, SQLx, Turso (local) / Cloudflare D1 (prod), Yew, Trunk, OpenTofu, Cloudflare Workers + Pages
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
A new `quotesdb` service is being added to the vibed mono-repo. The design was finalized in Phase 0. This plan covers:
|
||||
|
||||
0. **Task 0:** Create nbd project ticket `quotesdb` (stop after this — user will trigger the rest)
|
||||
1. **Task 1:** Bootstrap directory structure and design doc
|
||||
2. **Task 2:** Phase 1 — dispatch 4 parallel planning agents (each in a git worktree) to create nbd tickets
|
||||
3. **Task 3:** Merge planning branches
|
||||
4. **Task 4:** Phase 2 — dispatch 4 parallel implementation orchestrators
|
||||
|
||||
---
|
||||
|
||||
## Finalized Design (Phase 0 Output)
|
||||
|
||||
### Database Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE quotes (
|
||||
id TEXT PRIMARY KEY, -- NanoID (~21 chars)
|
||||
text TEXT NOT NULL,
|
||||
author TEXT NOT NULL,
|
||||
source TEXT, -- optional: book, speech, etc.
|
||||
date TEXT, -- optional: ISO date YYYY-MM-DD
|
||||
auth_code TEXT NOT NULL, -- 4-word passphrase e.g. ocean-table-purple-storm
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE quote_tags (
|
||||
quote_id TEXT NOT NULL REFERENCES quotes(id) ON DELETE CASCADE,
|
||||
tag TEXT NOT NULL,
|
||||
PRIMARY KEY (quote_id, tag)
|
||||
);
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
| Method | Path | Description | Auth |
|
||||
|--------|------|-------------|------|
|
||||
| GET | `/api/` | OpenAPI spec (JSON) | None |
|
||||
| GET | `/api/quotes` | List quotes, 10/page. Query: `?page=N&author=X&tag=Y` | None |
|
||||
| GET | `/api/quotes/random` | Random quote | None |
|
||||
| GET | `/api/quotes/:id` | Get quote by NanoID | None |
|
||||
| PUT | `/api/quotes` | Create a quote | None (auth_code optional in body) |
|
||||
| POST | `/api/quotes/:id` | Update a quote | `X-Auth-Code` header |
|
||||
| DELETE | `/api/quotes/:id` | Delete a quote | `X-Auth-Code` header |
|
||||
|
||||
**Note:** `GET /api/quotes/random` must be registered BEFORE `GET /api/quotes/:id` in the router.
|
||||
|
||||
### Request/Response Shapes
|
||||
|
||||
**PUT /api/quotes** — Create
|
||||
```json
|
||||
// Request body (auth_code optional — generated if omitted)
|
||||
{
|
||||
"text": "...",
|
||||
"author": "...",
|
||||
"source": "Stanford Commencement 2005",
|
||||
"tags": ["motivation"],
|
||||
"date": "2005-06-12",
|
||||
"auth_code": "ocean-table-purple-storm"
|
||||
}
|
||||
|
||||
// Response 201
|
||||
{
|
||||
"quote": { "id": "V1StG...", "text": "...", "author": "...", ... },
|
||||
"auth_code": "ocean-table-purple-storm"
|
||||
}
|
||||
```
|
||||
|
||||
**GET /api/quotes** — List
|
||||
```json
|
||||
{
|
||||
"quotes": [...],
|
||||
"page": 1,
|
||||
"total_pages": 4,
|
||||
"total_count": 38
|
||||
}
|
||||
```
|
||||
|
||||
**Error responses:** `{ "error": "message" }` with appropriate HTTP status.
|
||||
|
||||
### Auth
|
||||
|
||||
- No user accounts. Each quote has an `auth_code` (4-word passphrase).
|
||||
- Auth codes are stored **plaintext**.
|
||||
- Provided via `X-Auth-Code` header for update/delete.
|
||||
- On mismatch: `403 Forbidden`.
|
||||
- Auth code is always returned in the create response.
|
||||
|
||||
### Frontend Pages (Yew)
|
||||
|
||||
| Route | Page |
|
||||
|-------|------|
|
||||
| `/` | Home — random quote + "Browse all" link |
|
||||
| `/browse` | Paginated list with author/tag filter controls |
|
||||
| `/quotes/:id` | Single quote — view, edit (auth prompt), delete (auth prompt) |
|
||||
| `/author/:name` | All quotes by an author |
|
||||
| `/submit` | New quote form |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Bootstrap Project Structure
|
||||
|
||||
**Step 1: Create the quotesdb branch**
|
||||
```bash
|
||||
git checkout -b quotesdb
|
||||
```
|
||||
|
||||
**Step 2: Create directory skeleton**
|
||||
|
||||
```
|
||||
quotesdb/
|
||||
├── api/
|
||||
│ ├── Cargo.toml
|
||||
│ ├── src/
|
||||
│ │ ├── main.rs
|
||||
│ │ └── tests.rs
|
||||
│ ├── tests/
|
||||
│ ├── docs/
|
||||
│ │ ├── PLANNING.md
|
||||
│ │ └── ARCHITECTURE.md
|
||||
│ ├── flake.nix
|
||||
│ └── README.md
|
||||
├── ui/
|
||||
│ ├── Cargo.toml
|
||||
│ ├── src/
|
||||
│ │ ├── main.rs
|
||||
│ │ └── tests.rs
|
||||
│ ├── index.html
|
||||
│ ├── Trunk.toml
|
||||
│ ├── docs/
|
||||
│ │ ├── PLANNING.md
|
||||
│ │ └── ARCHITECTURE.md
|
||||
│ ├── flake.nix
|
||||
│ └── README.md
|
||||
├── tests/
|
||||
│ ├── Cargo.toml
|
||||
│ ├── tests/
|
||||
│ ├── docs/
|
||||
│ │ └── PLANNING.md
|
||||
│ └── README.md
|
||||
├── infra/
|
||||
│ └── main.tf
|
||||
└── docs/
|
||||
├── PLANNING.md
|
||||
├── ARCHITECTURE.md
|
||||
└── plans/
|
||||
└── 2026-02-27-quotesdb-design.md
|
||||
```
|
||||
|
||||
**Step 3: Write design doc**
|
||||
|
||||
Write the finalized design (from this plan's "Finalized Design" section) to `quotesdb/docs/plans/2026-02-27-quotesdb-design.md`.
|
||||
|
||||
**Step 4: Stub Cargo.toml files**
|
||||
|
||||
`quotesdb/api/Cargo.toml`:
|
||||
```toml
|
||||
[package]
|
||||
name = "quotesdb-api"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../../common" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
strip = true
|
||||
codegen-units = 1
|
||||
```
|
||||
|
||||
`quotesdb/ui/Cargo.toml`:
|
||||
```toml
|
||||
[package]
|
||||
name = "quotesdb-ui"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../../common" }
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
strip = true
|
||||
codegen-units = 1
|
||||
```
|
||||
|
||||
`quotesdb/tests/Cargo.toml`:
|
||||
```toml
|
||||
[package]
|
||||
name = "quotesdb-tests"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
```
|
||||
|
||||
**Step 5: Commit skeleton**
|
||||
```bash
|
||||
git add quotesdb/
|
||||
git commit -m "chore(quotesdb): bootstrap project skeleton and design doc"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Phase 1 — Parallel Planning Agents
|
||||
|
||||
> **Required skill:** Use `superpowers:dispatching-parallel-agents` before dispatching.
|
||||
|
||||
Dispatch 4 agents IN PARALLEL (single message, 4 Task tool calls). Each works in a dedicated git worktree on its own branch. Each agent's job is to:
|
||||
|
||||
1. Explore the design doc at `quotesdb/docs/plans/2026-02-27-quotesdb-design.md`
|
||||
2. Plan their domain thoroughly
|
||||
3. Create nbd tickets for every piece of work in their domain
|
||||
4. Commit their tickets on their branch
|
||||
|
||||
The nbd tool is available in the devshell. Tickets live in `.nbd/tickets/`. Use `nbd` to create and manage tickets.
|
||||
|
||||
### Agent 1: api-planner
|
||||
|
||||
**Branch:** `quotesdb/api`
|
||||
**Directory:** `quotesdb/api/`
|
||||
|
||||
**Prompt:**
|
||||
> You are a senior Rust backend engineer. Your job is to plan and ticket all backend API work for the `quotesdb` project.
|
||||
>
|
||||
> Read the design doc at `quotesdb/docs/plans/2026-02-27-quotesdb-design.md` for full context.
|
||||
>
|
||||
> The backend is:
|
||||
> - Rust, Axum, Tokio
|
||||
> - Target: Cloudflare Workers (workers-rs crate)
|
||||
> - Database: SQLx with Turso (local file-based SQLite) for dev, Cloudflare D1 in production
|
||||
> - Auto-generated OpenAPI spec required
|
||||
>
|
||||
> Create one nbd ticket per logical work item. Typical tickets include:
|
||||
> - Set up Cargo.toml with all dependencies
|
||||
> - Implement database migrations (schema creation)
|
||||
> - Implement each API endpoint (list, get, random, create, update, delete)
|
||||
> - Implement auth code generation (4-word passphrase)
|
||||
> - Implement NanoID generation for quote IDs
|
||||
> - Implement pagination logic
|
||||
> - Implement tag filtering (join with quote_tags)
|
||||
> - Implement OpenAPI spec generation
|
||||
> - Write unit tests for each handler
|
||||
> - Write README.md, PLANNING.md, ARCHITECTURE.md
|
||||
>
|
||||
> Work on branch `quotesdb/api` (use git worktrees). Each ticket should have enough detail for a developer to implement it independently.
|
||||
|
||||
### Agent 2: ui-planner
|
||||
|
||||
**Branch:** `quotesdb/ui`
|
||||
**Directory:** `quotesdb/ui/`
|
||||
|
||||
**Prompt:**
|
||||
> You are a senior Rust frontend engineer with strong design sensibilities. Your job is to plan and ticket all frontend UI work for the `quotesdb` project.
|
||||
>
|
||||
> Read the design doc at `quotesdb/docs/plans/2026-02-27-quotesdb-design.md` for full context.
|
||||
>
|
||||
> The frontend is:
|
||||
> - Rust + Yew compiled to Wasm (wasm32-unknown-unknown)
|
||||
> - Build tool: Trunk (`trunk serve` for dev)
|
||||
> - Hosted on Cloudflare Pages
|
||||
>
|
||||
> Pages to build:
|
||||
> - `/` — Home: random quote of the day + "Browse all" link
|
||||
> - `/browse` — Paginated quote list with author/tag filter controls
|
||||
> - `/quotes/:id` — Single quote view + edit/delete forms (auth code prompt)
|
||||
> - `/author/:name` — All quotes by an author
|
||||
> - `/submit` — New quote submission form
|
||||
>
|
||||
> Create one nbd ticket per logical work item. Typical tickets include:
|
||||
> - Set up Cargo.toml and Trunk.toml with all dependencies
|
||||
> - Set up Yew app shell and routing
|
||||
> - Implement each page component
|
||||
> - Implement API client (fetch calls to backend)
|
||||
> - Implement auth code prompt/modal
|
||||
> - Implement pagination component
|
||||
> - Write README.md, PLANNING.md, ARCHITECTURE.md
|
||||
>
|
||||
> Work on branch `quotesdb/ui` (use git worktrees). Each ticket should have enough detail for a developer to implement it independently.
|
||||
|
||||
### Agent 3: qa-planner
|
||||
|
||||
**Branch:** `quotesdb/qa`
|
||||
**Directory:** `quotesdb/tests/`
|
||||
|
||||
**Prompt:**
|
||||
> You are a senior QA engineer specializing in Rust integration testing. Your job is to plan and ticket all integration test work for the `quotesdb` project.
|
||||
>
|
||||
> Read the design doc at `quotesdb/docs/plans/2026-02-27-quotesdb-design.md` for full context.
|
||||
>
|
||||
> Integration tests live in `quotesdb/tests/` as a separate Rust crate. Tests should:
|
||||
> - Spin up the API server with an in-memory SQLite database
|
||||
> - Make real HTTP requests to test each endpoint
|
||||
> - Verify correct behavior for happy paths and error cases
|
||||
>
|
||||
> Create one nbd ticket per logical test suite. Typical tickets include:
|
||||
> - Set up test harness (test server, in-memory DB)
|
||||
> - Test quote creation (valid body, auth code generation, auth code provided by user)
|
||||
> - Test quote retrieval (by ID, not found)
|
||||
> - Test quote listing (pagination, author filter, tag filter)
|
||||
> - Test random quote endpoint
|
||||
> - Test quote update (valid auth, wrong auth, not found)
|
||||
> - Test quote deletion (valid auth, wrong auth, not found)
|
||||
> - Test OpenAPI spec endpoint
|
||||
> - Write README.md
|
||||
>
|
||||
> Work on branch `quotesdb/qa` (use git worktrees). Each ticket should have enough detail for a developer to implement it independently.
|
||||
|
||||
### Agent 4: infra-planner
|
||||
|
||||
**Branch:** `quotesdb/infra`
|
||||
**Directory:** `quotesdb/infra/`
|
||||
|
||||
**Prompt:**
|
||||
> You are a Terraform/OpenTofu expert. Your job is to plan and ticket all infrastructure work for the `quotesdb` project.
|
||||
>
|
||||
> Read the design doc at `quotesdb/docs/plans/2026-02-27-quotesdb-design.md` for full context.
|
||||
>
|
||||
> Infrastructure uses OpenTofu with the Cloudflare provider. Resources needed:
|
||||
> - Cloudflare Worker for the backend API
|
||||
> - Cloudflare D1 database (bound to the worker)
|
||||
> - Cloudflare Pages project for the frontend
|
||||
> - Custom domain: `quotes.elijah.run` for the frontend
|
||||
>
|
||||
> Create one nbd ticket per logical work item. Typical tickets include:
|
||||
> - Set up OpenTofu project (providers, state backend)
|
||||
> - Define Cloudflare Worker resource and build config
|
||||
> - Define Cloudflare D1 database resource and binding
|
||||
> - Define Cloudflare Pages project with custom domain
|
||||
> - Write README.md for infra setup instructions
|
||||
>
|
||||
> Work on branch `quotesdb/infra` (use git worktrees). Each ticket should have enough detail for a developer to implement it independently.
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Merge Planning Branches
|
||||
|
||||
After all 4 Phase 1 agents complete:
|
||||
|
||||
**Step 1: Review tickets from each branch**
|
||||
```bash
|
||||
git log quotesdb/api --oneline
|
||||
git log quotesdb/ui --oneline
|
||||
git log quotesdb/qa --oneline
|
||||
git log quotesdb/infra --oneline
|
||||
```
|
||||
|
||||
**Step 2: Merge all planning branches into `quotesdb`**
|
||||
```bash
|
||||
git checkout quotesdb
|
||||
git merge quotesdb/api
|
||||
git merge quotesdb/ui
|
||||
git merge quotesdb/qa
|
||||
git merge quotesdb/infra
|
||||
```
|
||||
|
||||
**Step 3: Resolve any conflicts, commit**
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Phase 2 — Parallel Implementation Orchestrators
|
||||
|
||||
> **Required skill:** Use `superpowers:dispatching-parallel-agents` before dispatching.
|
||||
|
||||
Dispatch 4 orchestrator agents IN PARALLEL. Each orchestrator:
|
||||
1. Lists all tickets for their domain
|
||||
2. Dispatches a fresh sub-agent per ticket (one at a time — complete one before starting the next)
|
||||
3. Reviews the sub-agent's work after each ticket
|
||||
4. Continues to the next ticket
|
||||
|
||||
### Implementation agent instructions (for each domain):
|
||||
|
||||
Each orchestrator should prompt its sub-agents with:
|
||||
- Full design context from `quotesdb/docs/plans/2026-02-27-quotesdb-design.md`
|
||||
- The specific ticket to implement
|
||||
- Validation commands to run: `cargo fmt && cargo check && cargo clippy && cargo test`
|
||||
- Conventional commit format: `feat(quotesdb-api): ...`
|
||||
|
||||
### Domain orchestrators:
|
||||
|
||||
**api-orchestrator** — works in `quotesdb/api/`, dispatches 1 sub-agent per api ticket
|
||||
**ui-orchestrator** — works in `quotesdb/ui/`, dispatches 1 sub-agent per ui ticket
|
||||
**qa-orchestrator** — works in `quotesdb/tests/`, dispatches 1 sub-agent per qa ticket
|
||||
**infra-orchestrator** — works in `quotesdb/infra/`, dispatches 1 sub-agent per infra ticket
|
||||
|
||||
> **Note:** api and tests must share an API contract. If the api-orchestrator makes endpoint changes, update the design doc and notify the qa-orchestrator.
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
After Phase 2 completes:
|
||||
|
||||
**Backend:**
|
||||
```bash
|
||||
cd quotesdb/api
|
||||
cargo fmt && cargo check && cargo clippy && cargo test
|
||||
cargo run # starts local server
|
||||
```
|
||||
|
||||
**Frontend:**
|
||||
```bash
|
||||
cd quotesdb/ui
|
||||
trunk serve # starts dev server at localhost:8080
|
||||
```
|
||||
|
||||
**Integration tests:**
|
||||
```bash
|
||||
cd quotesdb/tests
|
||||
cargo test
|
||||
```
|
||||
|
||||
**Infrastructure:**
|
||||
```bash
|
||||
cd quotesdb/infra
|
||||
tofu plan # dry-run Cloudflare infra
|
||||
```
|
||||
|
||||
**Manual smoke test:**
|
||||
```bash
|
||||
# Create a quote
|
||||
curl -X PUT http://localhost:8787/api/quotes \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text":"Hello world","author":"Test"}'
|
||||
|
||||
# List quotes
|
||||
curl http://localhost:8787/api/quotes
|
||||
|
||||
# Random quote
|
||||
curl http://localhost:8787/api/quotes/random
|
||||
```
|
||||
Loading…
Reference in New Issue