Built by NOUMENON, an AI build engine. One prompt to a production-ready API. Follow the build: @noumenon.ai
A fully authenticated REST API for todo management: JWT auth, per-user data isolation, server-side input validation, parameterized SQL (injection-safe), secret hygiene, and a health endpoint.
Built from one prompt, then tested and gate-checked before shipping.
NOUMENON: build a simple todo list API with auth. Node.js.
Show me the phases, run the tests, enforce the gates.
- A working authenticated API
- 40 tests, 40 passing
- 7 security gates, all verified in code
- A phased build with git checkpoints (b1 p1 through p4)
- A broken security gate caught and fixed during the build
- Scope drift flagged, disclosed, then removed to match the spec
| Gate | Status | Evidence |
|---|---|---|
| Data isolation | PASS | Every todo query is WHERE user_id = ? bound to req.userId; all parameterized prepared statements |
| user_id server-derived | PASS | req.userId is set only from the jwt.verify() payload; a client-supplied value is never trusted |
| Auth rejection | PASS | Missing token returns 401; cross-user access returns 404; both tested |
| Input validation | PASS | src/validate.js, bounded and allow-listed, parameterized SQL only |
| Secret hygiene | PASS | .gitignore blocks .env*, *.db, and keys; nothing sensitive tracked; secrets fail fast on boot |
| Health and bind guard | PASS | /health requires no auth; loopback-only bind enforced in src/config.js |
| Data map | PASS | docs/DATA_MAP.md shipped |
40/40 passing (Jest + supertest)
Coverage includes:
- Every endpoint happy path
- Bad-input and 404 error paths
- SQL injection stored as data, not executed
- No token -> 401
- Valid token, wrong user -> 404
The secret-scan pre-commit hook hard-required ripgrep and ran the matcher inside an if condition. With set -e, a missing rg made the condition evaluate false, so the hook passed silently. A fail-open: it could never block a secret if ripgrep was absent.
The fix makes the scanner tool-agnostic: prefer rg, fall back to GNU grep -P, and exit non-zero if neither exists (fail closed). Verified with a real commit containing a planted AKIA... key, which is now rejected; a clean tree still passes.
The engine added three things that were not in the original spec:
Idempotency-Keyhandling forPOST /todosexpress-rate-limiton the auth routes- a
pinologging dependency
They were flagged to the operator rather than shipped silently. The operator chose to bring the build back to the bare spec, so the idempotency feature and the two extra dependencies were removed. Structured request logging was kept, because the spec called for observability, but it now uses a small built-in JSON logger with no third-party dependency. This is the reviewer-implementer loop completing: drift surfaced, decision made, build corrected.
- Node.js and Express 5
- better-sqlite3
- jsonwebtoken (JWT)
- bcrypt
- built-in JSON structured logging (no logging dependency)
- Jest and supertest
Requires Node.js >= 22.13.1.
npm install
npm run setup # creates .env with a freshly generated JWT_SECRET
npm test # 40/40
npm start # binds to 127.0.0.1:3000 by defaultnpm run setup writes a local .env (gitignored) from .env.example with a
secure random JWT_SECRET. It will not overwrite an existing .env. The server
refuses to start with the placeholder secret by design.
The server binds to a loopback interface by default and refuses non-loopback
hosts unless explicitly configured. If port 3000 is already in use on your
machine, set a different PORT in .env (for example PORT=4010); the server
prints a clear message instead of crashing.
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /auth/register | None | Register a user |
| POST | /auth/login | None | Log in, returns a JWT |
| GET | /todos | JWT | List your todos |
| POST | /todos | JWT | Create a todo |
| GET | /todos/:id | JWT | Get one of your todos |
| PUT | /todos/:id | JWT | Update your todo |
| DELETE | /todos/:id | JWT | Delete your todo |
| GET | /health | None | Health check |
NOUMENON is an AI build engine. You describe what you want; it architects it, writes it, tests it, enforces security gates, flags scope drift, and ships it.
Follow the build: @noumenon.ai
This repo is a proof of concept. Every gate is real and every test is real. Read the code and verify it yourself.