You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

14 KiB

+++ title = "quotesdb" priority = 8 status = "todo" ticket_type = "project" dependencies = ["ce1e4f", "f3dc74", "c3503b", "25c413"] +++

QuotesDB Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. For Claude: SUGGESTED SUB-SKILL: Use agent-development for agent dispatch For Claude: SUGGESTED SUB-SKILL: Use dispatching-parallel-agents for agent dispatch For Claude: SUGGESTED SUB-SKILL: Use subagent-driven-development for agent dispatch For Claude: SUGGESTED SUB-SKILL: Use verification-before-completion for verification For Claude: SUGGESTED SUB-SKILL: Use finishing-a-development-branch for verification For Claude: SUGGESTED SUB-SKILL: Use using-git-worktrees for parallel work For Claude: SUGGESTED SUB-SKILL: Use test-driven-development for development workflow

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:

  1. Task 0: Create nbd project ticket quotesdb (stop after this — user will trigger the rest)
  2. Task 1: Bootstrap directory structure and design doc
  3. Task 2: Phase 1 — dispatch 4 parallel planning agents (each in a git worktree) to create nbd tickets
  4. Task 3: Merge planning branches
  5. Task 4: Phase 2 — dispatch 4 parallel implementation orchestrators

Finalized Design (Phase 0 Output)

Database Schema

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

// 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

{
  "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

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:

[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:

[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:

[package]
name = "quotesdb-tests"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"

Step 5: Commit skeleton

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

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

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:

cd quotesdb/api
cargo fmt && cargo check && cargo clippy && cargo test
cargo run   # starts local server

Frontend:

cd quotesdb/ui
trunk serve   # starts dev server at localhost:8080

Integration tests:

cd quotesdb/tests
cargo test

Infrastructure:

cd quotesdb/infra
tofu plan   # dry-run Cloudflare infra

Manual smoke test:

# 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