feat: Todo MVP — Express REST API with in-memory store and frontend#1
feat: Todo MVP — Express REST API with in-memory store and frontend#1algorithm-conduction wants to merge 1 commit into
Conversation
…vanilla JS frontend Adds all four CRUD endpoints (GET/POST/PATCH/DELETE /api/todos), an in-memory store, a single-page HTML frontend, and vitest integration tests covering every acceptance scenario from specs/api.md. All 8 tests pass. EUPL-1.2 licence headers on every new file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
[WARNING] Missing HTTP security headers |
|
[WARNING] No maximum length validation on if (!title || typeof title !== 'string' || title.length > 500) {
return res.status(400).json({ error: 'title must be a non-empty string up to 500 characters' });
}Also consider using a package such as |
|
[SUGGESTION] No authentication or authorisation on any API endpoint |
|
[SUGGESTION] No rate limiting on API endpoints import rateLimit from 'express-rate-limit';
app.use(rateLimit({ windowMs: 60_000, max: 100 })); |
|
[SUGGESTION] if (typeof completed !== 'boolean') {
return res.status(400).json({ error: 'completed must be a boolean' });
} |
Hydra Security Review — Clyde BarcodeTool results
No automated tool produced any findings. The items above are from manual code review. Summary
The two WARNINGs are not individually exploitable under typical conditions for an MVP, but the title-length issue is a realistic low-effort DoS vector if the service is ever network-accessible. Neither WARNING rises to a hard block for an MVP, but both should be tracked and resolved before any production deployment. Verdict{ "pass": true, "blocking": [] } |
|
[CRITICAL] Server never binds to a port — // at the bottom of src/server.js
if (process.argv[1] === new URL(import.meta.url).pathname) {
const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => console.log(`Listening on http://localhost:${PORT}`));
} |
|
[CRITICAL] Server never binds to a port — if (process.argv[1] === new URL(import.meta.url).pathname) {
const PORT = process.env.PORT ?? 3000;
app.listen(PORT, () => console.log(`Listening on http://localhost:${PORT}`));
} |
|
[WARNING] No lint script configured — style violations go undetected |
|
[WARNING] |
|
[WARNING] No ESLint (lint) script defined in package.json |
|
[WARNING] |
|
[WARNING] PATCH endpoint passes |
|
[WARNING] Vitest dependency chain has 4 moderate-severity CVEs (esbuild GHSA-67mh-4wv8-2f99) |
|
[SUGGESTION] |
|
[SUGGESTION] Frontend fetch calls have no error handling |
|
[SUGGESTION] PR description spec reference URL points to a non-existent path |
Hydra Review — Juan Claude van DammeTests: 8/8 passed ( Summary of findings
No CRITICAL findings. All 8 spec scenarios pass. The WARNINGs should be addressed before merge — in particular, { "pass": true, "blocking": [] } |
Summary
Implements the Todo MVP as specified in
/spec/design.md. A Node.js + Express REST API with an in-memory store exposes four CRUD endpoints for todo items. A vanilla HTML/JS single-page frontend consumes the API directly. All code carries EUPL-1.2 licence headers as required by the Common Ground conventions.Spec Reference
https://github.com/algorithm-conduction/todo-app/blob/hydra/spec/openspec/design.md
Changes
package.json— Node.js project initialised with express, supertest, vitest;"type": "module"for ESMsrc/store.js— In-memory todo store withlist,create,update,remove,reset; EUPL-1.2 headersrc/server.js— Express app wiring all four REST endpoints; EUPL-1.2 headerpublic/index.html— Single-page frontend: add, complete, and delete todos via fetch; EUPL-1.2 headertest/api.test.js— Vitest + supertest integration tests for all four endpoints; EUPL-1.2 header.gitignore— Excludesnode_modules/andpackage-lock.jsonTest Coverage
test/api.test.js— 8 tests covering all spec scenarios: