Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules/
dist/
coverage/
.vitest/
*.tsbuildinfo
.npm/
.env
.DS_Store
*.log
154 changes: 111 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,111 @@
# Candidate Assessment: Spec-Driven Development With Codegen Tools

This assessment evaluates how you use modern code generation tools (for example `5.2-Codex`, `Claude`, `Copilot`, and similar) to design, build, and test a software application using a spec-driven development pattern. You may build a frontend, a backend, or both.

## Goals
- Build a working application with at least one meaningful feature.
- Create a testing framework to validate the application.
- Demonstrate effective use of code generation tools to accelerate delivery.
- Show clear, maintainable engineering practices.

## Deliverables
- Application source code in this repository.
- A test suite and test harness that can be run locally.
- Documentation that explains how to run the app and the tests.

## Scope Options
Pick one:
- Frontend-only application.
- Backend-only application.
- Full-stack application.

Your solution should include at least one real workflow, for example:
- Create and view a resource.
- Search or filter data.
- Persist data in memory or storage.

## Rules
- You must use a code generation tool (for example `5.2-Codex`, `Claude`, or similar). You can use multiple tools.
- You must build the application and a testing framework for it.
- The application and tests must run locally.
- Do not include secrets or credentials in this repository.

## Evaluation Criteria
- Working product: Does the app do what it claims?
- Test coverage: Do tests cover key workflows and edge cases?
- Engineering quality: Clarity, structure, and maintainability.
- Use of codegen: How effectively you used tools to accelerate work.
- Documentation: Clear setup and run instructions.

## What to Submit
- When you are complete, put up a Pull Request against this repository with your changes.
- A short summary of your approach and tools used in your PR submission
- Any additional information or approach that helped you.
# Task Management API (Spec-Driven)

Backend-only application implementing a task workflow with schema validation, modular architecture, and deterministic tests.

- Runtime requirement: Node.js 20+
- Persistence model: in-memory store only (no database)
- Test model: deterministic unit and integration tests

## PR-Style Summary
- Built a complete Express + TypeScript API with separated routes/controllers/services/schemas/middleware.
- Added explicit request/response schema validation using Zod at application boundaries.
- Added reusable fixtures/helpers and split tests into unit/integration suites.
- Added parameterized tests for invalid payloads and query validation.
- Added repository hygiene updates (`.gitignore`, clean structure, no generated artifacts committed).

Detailed PR notes are in [docs/PR_DESCRIPTION.md](docs/PR_DESCRIPTION.md).
Specification index is in [SPECS/INDEX.md](SPECS/INDEX.md).

## Architecture Overview
- `src/app.ts`: app composition and middleware registration
- `src/server.ts`: runtime entrypoint
- `src/routes/taskRoutes.ts`: endpoint routing
- `src/controllers/taskController.ts`: HTTP boundary handlers
- `src/services/taskService.ts`: business logic + in-memory store
- `src/schemas/taskSchema.ts`: request/response/query schemas
- `src/middleware/errorHandler.ts`: central error normalization
- `src/utils/id.ts`: deterministic id utility

## API
- `POST /tasks`
- body: `{ title: string, description?: string, status?: "todo"|"in_progress"|"done" }`
- returns `201` with created task
- `GET /tasks?status=<status>`
- optional status filter
- returns `200` with `{ tasks: Task[] }`
- `GET /tasks/:id`
- returns `200` task or `404` if missing
- `GET /health`
- returns `200 { status: "ok" }`

## Setup
```bash
npm install
```

## Run
```bash
npm run dev
```

Production-style run:
```bash
npm run build
npm run start
```

## Smoke Test
```bash
# 1) Health check (expected: 200)
curl -i http://localhost:3000/health

# 2) Create task (expected: 201)
curl -i -X POST http://localhost:3000/tasks \
-H "content-type: application/json" \
-d '{"title":"Smoke task","status":"todo"}'

# 3) List tasks (expected: 200)
curl -i http://localhost:3000/tasks

# 4) Get task by id (expected: 200 for existing id, 404 for unknown id)
curl -i http://localhost:3000/tasks/task-1
```

## Test
```bash
npm test
```

## Coverage
```bash
npm run coverage
```
- Uses Vitest with the V8 coverage provider.
- Reports are generated in `coverage/` (text summary, `coverage-final.json`, and HTML report).

Optional watch mode:
```bash
npm run test:watch
```

## Quality Checks
```bash
npm run lint
npm run build
```

## Configuration
- `PORT` (optional): default `3000`

## Troubleshooting
- If TypeScript errors appear, run `npm run lint` to surface typing issues.
- If tests fail after local edits, rerun with `npm test` to confirm deterministic behavior.
- If port `3000` is in use, start with `PORT=3001 npm run dev`.

## Assumptions
- Assessment scope accepts in-memory persistence.
- No authentication/authorization required.
- Node.js 20+ is available.

## Tools Used
- GPT-5 Codex for spec-driven implementation workflow and refactoring.
42 changes: 42 additions & 0 deletions SPECS/01-system-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Feature Spec: System Overview and Scope

## Goal
- Define the implemented system boundary, objectives, and architecture without introducing new behavior.

## Scope
- In:
- Problem definition, goals, non-goals, assumptions, architecture, and system boundaries for the current backend.
- Out:
- API request/response contract details (see `02-api-contract.md`).
- Validation/error classification details (see `04-validation-error-semantics.md`).

## Requirements
- Constraints:
- Must reflect current implementation only (`src/app.ts`, `src/server.ts`).
- Must keep architecture decomposition explicit by layer.
- Non-goals:
- No database persistence.
- No authentication/authorization.
- No frontend or task update/delete workflows.
- Assumptions:
- Node.js 20+ runtime.
- In-memory process-local state.
- Traceability:
- `src/server.ts`
- `src/app.ts`
- `src/routes/taskRoutes.ts`
- `src/controllers/taskController.ts`
- `src/services/taskService.ts`
- `src/schemas/taskSchema.ts`
- `src/middleware/errorHandler.ts`

## Acceptance Criteria
- [x] Problem definition and system goals are documented.
- [x] Non-goals and runtime assumptions are explicit.
- [x] High-level architecture is documented by module boundaries.
- [x] System input/output boundaries are documented.
- [x] Traceability to implementation files is provided.

## Examples
- Input boundary example: JSON request body for `POST /tasks`.
- Output boundary example: JSON error payload from middleware.
102 changes: 102 additions & 0 deletions SPECS/02-api-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Feature Spec: API Contract

## Goal
- Define the exact public HTTP interface implemented by the service, including success and failure contracts.

## Scope
- In:
- Documented endpoints, request/query schemas, response shapes, status codes, and examples.
- Out:
- Internal persistence mechanics and service-level implementation details.

## Requirements
- Constraints:
- Must match route/controller behavior exactly.
- Must not include unimplemented endpoints.
- Endpoints:
- `GET /health`
- `POST /tasks`
- `GET /tasks`
- `GET /tasks/:id`
- Error object structures:
- `400` validation payload from Zod failures.
- `404` domain not found and route not found payloads.
- `500` fallback payload.
- Traceability:
- `src/routes/taskRoutes.ts`
- `src/controllers/taskController.ts`
- `src/schemas/taskSchema.ts`
- `src/middleware/errorHandler.ts`

## Acceptance Criteria
- [x] All implemented public endpoints are documented.
- [x] Request/query and response contracts are documented.
- [x] Status code semantics align with implementation.
- [x] Positive and negative examples are present.
- [x] Error object structures are documented.

## Examples
### Shared Types
- `TaskStatus`: `"todo" | "in_progress" | "done"`
- `Task`: `{ id, title, description?, status, createdAt }`

### GET /health
- Success: `200 { "status": "ok" }`

### POST /tasks
- Request body:
- `title: string` (trimmed, min 1, max 120)
- `description?: string` (trimmed, max 500)
- `status?: TaskStatus` (default `"todo"`)
- Success: `201` with `Task`.
- Validation failure: `400`.

Positive example:
```json
{
"title": "Write deterministic tests",
"description": "Cover edge cases",
"status": "todo"
}
```

Negative example:
```json
{
"title": "Write deterministic tests",
"status": "blocked"
}
```

### GET /tasks
- Query: `status?: TaskStatus`
- Success: `200 { "tasks": Task[] }`
- Validation failure: `400`

Positive example: `GET /tasks?status=done`

Negative example: `GET /tasks?status=invalid`

### GET /tasks/:id
- Success: `200` with `Task`
- Not found: `404 { "error": "Task not found" }`

### Error Structures
```json
{
"error": "ValidationError",
"details": [{ "path": "status", "message": "Invalid enum value" }]
}
```

```json
{ "error": "Task not found" }
```

```json
{ "error": "Not Found" }
```

```json
{ "error": "Internal Server Error" }
```
39 changes: 39 additions & 0 deletions SPECS/03-domain-model-invariants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Feature Spec: Domain Model and Invariants

## Goal
- Define domain entities, constraints, transitions, and invariants enforced by the implemented service layer.

## Scope
- In:
- Task entity model, storage model, invariants, and state transitions for implemented operations.
- Out:
- HTTP status/error handling rules (see `04-validation-error-semantics.md`).

## Requirements
- Constraints:
- `Task` fields must align with `src/types/task.ts` and `src/schemas/taskSchema.ts`.
- Invariants must reflect `TaskService` behavior only.
- Entity definition:
- `id`: non-empty string from `nextId()`.
- `title`: trimmed, non-empty, max 120.
- `description`: optional, max 500.
- `status`: `todo | in_progress | done`.
- `createdAt`: ISO datetime.
- Storage model:
- In-memory array in `TaskService`.
- Traceability:
- `src/types/task.ts`
- `src/schemas/taskSchema.ts`
- `src/services/taskService.ts`
- `src/utils/id.ts`

## Acceptance Criteria
- [x] Task entity fields and constraints are documented.
- [x] Storage model and lifecycle limits are documented.
- [x] Domain invariants are documented.
- [x] Implemented state transitions are documented.
- [x] Traceability to domain implementation exists.

## Examples
- Transition example: `POST /tasks` appends one new `Task` into in-memory storage.
- Invariant example: `listTasks("done")` returns only tasks with `status === "done"`.
36 changes: 36 additions & 0 deletions SPECS/04-validation-error-semantics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Feature Spec: Validation and Error Semantics

## Goal
- Define boundary-validation behavior and the exact error classification model used by the implemented API.

## Scope
- In:
- Request/response boundary validation strategy and 400/404/500 semantics.
- Out:
- Endpoint catalog details already defined in `02-api-contract.md`.

## Requirements
- Constraints:
- Validation must occur at controller boundaries using Zod schemas.
- Error classification must match middleware behavior.
- Error classification:
- `400 ValidationError`: request/query/response parsing failures.
- `404 Task not found`: missing task id from domain lookup.
- `404 Not Found`: unmatched route.
- `500 Internal Server Error`: non-classified exceptions.
- Traceability:
- `src/controllers/taskController.ts`
- `src/schemas/taskSchema.ts`
- `src/middleware/errorHandler.ts`

## Acceptance Criteria
- [x] Boundary validation strategy is documented.
- [x] Error classes and status mapping are documented.
- [x] Failure scenarios are documented with expected outcomes.
- [x] Semantics match implemented middleware/controller behavior.

## Examples
- Missing `title` on `POST /tasks` -> `400 ValidationError`.
- Invalid `status` query on `GET /tasks` -> `400 ValidationError`.
- Unknown id on `GET /tasks/:id` -> `404 Task not found`.
- Unmatched route -> `404 Not Found`.
Loading