Skip to content

Latest commit

 

History

History
144 lines (110 loc) · 8.68 KB

File metadata and controls

144 lines (110 loc) · 8.68 KB

Blueprint: Build a production-grade Todo List REST API with user authentication in Node.js.

Generated: 2026-06-03T16:49:41Z Classification: PUBLIC PRODUCT Applies: Gates 1-8 (all)

This Blueprint is a hard gate: no build phase begins until the checklist below is satisfied.

Gate 1 — Project classification

  • Q1: C: end users the builder does not know (public product) evidence: matched audience token: 'public'
  • Q2: C: writes to external APIs, databases, or filesystems evidence: matched external-write token: 'insert'
  • Q3: C: initiates, processes, or stores payment data evidence: matched money-process token: 'ach'
  • Q4: B: handles data belonging to the builder only evidence: matched owner-only data token: 'personal data'

Applicable gate checklists (MANDATORY)

Gate 2 — Working on a clean machine

  • All dependencies are explicitly declared
  • All dependencies are pinned to exact versions
  • A lock file exists and is committed
  • Setup instructions produce a working install in one command on a clean environment
  • Environment variables documented in .env.example with descriptions
  • Health check command exists and verifies the install worked
  • Minimum supported runtime version is stated explicitly

Gate 3 — Does not destroy the user's system

  • All write operations are scoped to a declared working directory
  • No writes outside the project directory without explicit user confirmation
  • Temp files are cleaned up on exit (try/finally)
  • No hardcoded absolute paths
  • Destructive operations require explicit confirmation or a documented --yes flag
  • A backup or dry-run option exists for destructive operations
  • All subprocess calls use the command allowlist (swarm/command_allowlist.py)
  • No shell=True in subprocess calls
  • All subprocess calls have explicit timeout values
  • The project does not modify system config or shell profile files

Gate 4 — Dependency license compliance

  • Every dependency reviewed against PERMITTED / CONDITIONAL / PROHIBITED list
  • pip-licenses or npx license-checker run; report committed
  • No GPL/AGPL/SSPL/Commons Clause dependencies in commercial builds
  • LICENSE file present at repo root
  • Third-party attribution surfaced where required

Gate 5 — API and service terms of service

  • Every external API listed in Blueprint.md
  • Rate limits documented and respected with backoff/retry
  • Allowed use cases confirmed (scraping, automation, commercial use)
  • Data usage terms confirmed (store / reprocess / resell)
  • Authentication method matches ToS requirements
  • High-risk APIs (OpenAI/Anthropic, Google, financial, social, payment) reviewed explicitly

Gate 6 — Data privacy and legal compliance

  • Privacy policy exists and is linked from the product
  • Data inventory documented (what, why, retention period)
  • User deletion path implemented (GDPR right to erasure)
  • Cookie/tracking consent flow exists if applicable
  • California opt-out and deletion path exists (CCPA)
  • PII never logged or sent to error tracking; scrubbing configured
  • Passwords hashed with bcrypt or argon2 (never plaintext or reversible)
  • Secrets stored encrypted at rest
  • User data isolation enforced (no cross-tenant reads)
  • Data retention policy enforced in code, not just documented

Gate 7 — Security baseline

  • Auth via proven library or service (Auth.js, Clerk, Supabase Auth, Firebase Auth)
  • Authorization checks are server-side
  • Admin routes are protected (not just hidden)
  • API keys and tokens expire (no indefinite credentials)
  • Rate limiting on all authentication endpoints
  • All user input validated for type, length, format
  • All database queries parameterized (no string concatenation)
  • File uploads validated by type, size, and content
  • Redirects validated against an allowlist (no open redirects)
  • HTML output escaped; CSP header set
  • HTTPS only in production
  • Secrets in env vars, never in code or config files
  • Generic error messages to users (no stack traces, no internals)
  • Dependencies scanned for CVEs before launch

Gate 8 — Commercial viability sanity check

  • Payment processor account approved for this business category
  • Terms of Service exist for the product
  • Refund policy exists and is displayed before purchase
  • No unsubstantiated claims in marketing copy
  • AI-generated content disclosed where required (EU AI Act, FTC, platform rules)
  • Regulated-industry disclaimers present if applicable

Plan

SCORES (Specificity / Feasibility / Spec-Match / Innovation / Risk → final)

  • The Visionary: 9 / 9 / 7 / 9 / 6 → 8.0 — concrete idempotency design, rides the isolation harness, stays in scope; lower spec-match (adds beyond the literal ask) and risk-breadth.
  • The Skeptic: 9 / 10 / 10 / 4 / 10 → 8.6 — every mitigation maps to a named "production-grade" failure mode the spec implies (WAL, fail-fast secret length, .changes===0→404, rate-limit, 72-byte bcrypt, body cap, JWT expiry, UNIQUE-on-email race).

WINNER: HYBRID — The Skeptic (backbone) + The Visionary (one innovation)

WHY THIS APPROACH: The spec literally says "production-grade" and lists Section-I security gates — that is the Skeptic's risk matrix verbatim, so it forms the spine. The Visionary's user-scoped Idempotency-Key is one in-scope, zero-dependency feature that hardens POST /todos against retry-duplication and double-proves the isolation model — genuine value the anti-bias/diversity rule rightly pushes me to include rather than defaulting to risk-only.

INCORPORATE:

  • From Visionary: user-scoped idempotency_keys table + ~15-line middleware inside POST /todos; +1 test (same key twice → one row, identical 201).
  • From Skeptic: WAL+busy_timeout; fail-fast if JWT_SECRET.length<32 or equals the example value; rate-limit on /auth/*; express.json({limit:'16kb'}); reject password >72 bytes / <8 chars; JWT expiresIn:'15m'; UNIQUE email → catch constraint → 409; central error handler (no stack leaks).

REJECT: Refresh tokens, account lockout, password reset (Skeptic+Hacker agree — out of scope, gold-plating).


FINAL BUILD PLAN

Stack: Node ≥22.13.1, Express, better-sqlite3, bcrypt (cost 12), jsonwebtoken, express-rate-limit, pino (structured logs), dotenv; Jest + supertest (dev).

Files

  • src/app.js — express app factory (json limit 16kb, pino-http, routes, central error handler). Export app separately from listen for supertest.
  • src/server.jsvalidateEnv() fail-fast → open DB → app.listen.
  • src/db.js — open connection; PRAGMA journal_mode=WAL; busy_timeout=5000; foreign_keys=ON; run migrations on boot.
  • src/migrations/001_init.sqlusers(id, email UNIQUE NOT NULL, password_hash, created_at); todos(id, user_id NOT NULL→users.id, title, completed INTEGER DEFAULT 0, created_at); idempotency_keys(key, user_id, response_status, response_body, created_at, PRIMARY KEY(key,user_id)).
  • src/auth/routes.jsPOST /auth/register (email-regex + len; bcrypt; INSERT, catch UNIQUE→409), POST /auth/login (lookup, bcrypt.compare, sign 15m JWT). Rate-limited.
  • src/auth/middleware.js — verify Authorization: Bearer, set req.userId (server-derived). Missing/invalid → 401.
  • src/todos/routes.js — all 5 routes; every query WHERE id=? AND user_id=?, parametrized; UPDATE/DELETE use .changes===0 → 404; idempotency check + persist in one transaction on POST.
  • src/validate.js — bound title (1–500 chars, string), completed (boolean), email, password (8–72 bytes).
  • health.js route → {status:'ok'}, no auth, no PII.
  • package.json (start, test), README.md, .env.example (no real values), .gitignore (.env*, *.db, secrets/, *.pem, *.key, *.token), docs/DATA_MAP.md.

Quality requirements (Advocate-level, ship in v1)

  • Consistent JSON error shape {error:{code,message}}; never leak stack/SQL. Generic 401 on bad creds (no user-enumeration). All inputs validated+bounded server-side before use. No secret/PII in any log line.

Tests (must pass)

  • Happy path each endpoint; bad-input 400; not-found 404; SQL-injection string in title/email is stored/escaped, not executed; no-token → 401; valid token, other user's todo id → 404; UPDATE/DELETE wrong-user → 404 via .changes===0; login rate-limit triggers; duplicate email → 409; idempotency: same key twice → one row + identical 201.

Verify: npm ci && npm test (all green) → node src/server.js boots with WAL + migrations, fails fast with missing/short JWT_SECRETcurl /health 200 → register/login/CRUD round-trip.