## 1. Project Bootstrap & Infrastructure - [x] 1.1 Initialise `package.json` with all required dependencies (Express, TypeScript, Joi, jsonwebtoken, bcryptjs, uuid, pg, redis, pino, helmet, cors, dotenv, jest, supertest, ts-jest, ESLint, Prettier) - [x] 1.2 Create `tsconfig.json` with strict mode enabled (all flags from README §6.4) - [x] 1.3 Create `.eslintrc.json` with `@typescript-eslint` plugin and no-`any` rule - [x] 1.4 Create `.prettierrc` - [x] 1.5 Create `jest.config.ts` with `ts-jest` preset and coverage thresholds (>80%) - [x] 1.6 Create `docker-compose.yml` with `postgres:14-alpine` and `redis:7-alpine` services - [x] 1.7 Create `.env.example` documenting all required environment variables (`DATABASE_URL`, `REDIS_URL`, `JWT_PRIVATE_KEY`, `JWT_PUBLIC_KEY`, `PORT`, etc.) ## 2. Shared Infrastructure - [x] 2.1 Create `src/types/index.ts` — all shared TypeScript interfaces (`IAgent`, `ICredential`, `IAuditEvent`, `ITokenPayload`, `ICreateAgentRequest`, `IUpdateAgentRequest`, etc.) - [x] 2.2 Create `src/utils/errors.ts` — full `SentryAgentError` hierarchy (`ValidationError`, `AgentNotFoundError`, `AgentAlreadyExistsError`, `CredentialError`, `AuthenticationError`, `AuthorizationError`, `RateLimitError`, `FreeTierLimitError`) - [x] 2.3 Create `src/utils/crypto.ts` — `generateClientSecret()` (sk_live_ prefix + 64 hex), `hashSecret(plain)` (bcrypt 10 rounds), `verifySecret(plain, hash)` (bcrypt compare) - [x] 2.4 Create `src/utils/jwt.ts` — `signToken(payload, privateKey)` (RS256), `verifyToken(token, publicKey)` (returns typed payload), `decodeToken(token)` (no verification) - [x] 2.5 Create `src/utils/validators.ts` — Joi schemas for `CreateAgentRequest`, `UpdateAgentRequest`, `TokenRequest`, `IntrospectRequest`, `RevokeRequest`, `GenerateCredentialRequest`, list query params - [x] 2.6 Create `src/db/pool.ts` — typed `pg.Pool` singleton, reads `DATABASE_URL` from env - [x] 2.7 Create `src/cache/redis.ts` — typed Redis client singleton, reads `REDIS_URL` from env - [x] 2.8 Create `src/db/migrations/001_create_agents.sql` — `agents` table (all fields from OpenAPI spec, `status` as varchar) - [x] 2.9 Create `src/db/migrations/002_create_credentials.sql` — `credentials` table (`credential_id`, `client_id`, `secret_hash`, `status`, `created_at`, `expires_at`, `revoked_at`) - [x] 2.10 Create `src/db/migrations/003_create_audit_events.sql` — `audit_events` table (`event_id`, `agent_id`, `action`, `outcome`, `ip_address`, `user_agent`, `metadata` JSONB, `timestamp`) - [x] 2.11 Create `src/db/migrations/004_create_tokens.sql` — `token_revocations` table (`jti`, `expires_at`) for soft revocation tracking (supplementary to Redis) - [x] 2.12 Create `npm run db:migrate` script to execute migrations in order ## 3. Middleware - [x] 3.1 Create `src/middleware/auth.ts` — Bearer token extraction from `Authorization` header, RS256 JWT verification, Redis revocation check, attaches decoded payload to `req.user`; throws `AuthenticationError` on failure - [x] 3.2 Create `src/middleware/rateLimit.ts` — Redis sliding window counter keyed by `client_id`; injects `X-RateLimit-*` headers on every response; throws `RateLimitError` at 100 req/min - [x] 3.3 Create `src/middleware/errorHandler.ts` — Express error middleware; maps `SentryAgentError` subclasses to HTTP status codes and `ErrorResponse` JSON; maps unknown errors to `500` ## 4. Agent Registry - [x] 4.1 Create `src/repositories/AgentRepository.ts` — typed methods: `create`, `findById`, `findByEmail`, `findAll` (with filters + pagination), `update`, `decommission`, `countByOwner`; all SQL in this file only - [x] 4.2 Create `src/services/AgentService.ts` — `registerAgent`, `getAgentById`, `listAgents`, `updateAgent`, `decommissionAgent`; enforces free-tier 100-agent limit; validates immutable fields on update; calls `AuditService` for all write operations; JSDoc on all public methods - [x] 4.3 Create `src/controllers/AgentController.ts` — HTTP handlers for all 5 agent endpoints; Joi validation using `validators.ts`; delegates to `AgentService`; no business logic - [x] 4.4 Create `src/routes/agents.ts` — Express router wiring `AgentController` handlers to paths with `auth` and `rateLimit` middleware ## 5. OAuth 2.0 Token Service - [x] 5.1 Create `src/repositories/TokenRepository.ts` — `addToRevocationList(jti, expiresAt)`, `isRevoked(jti)` (checks Redis first, then DB); `incrementMonthlyCount(clientId)`, `getMonthlyCount(clientId)` (Redis-backed) - [x] 5.2 Create `src/services/OAuth2Service.ts` — `issueToken` (validates client credentials via bcrypt, checks agent status, enforces 10k monthly limit, signs RS256 JWT, writes audit event), `introspectToken` (verifies + checks revocation), `revokeToken` (adds JTI to Redis + DB revocation list, writes audit event); JSDoc on all public methods - [x] 5.3 Create `src/controllers/TokenController.ts` — HTTP handlers for `POST /token`, `POST /token/introspect`, `POST /token/revoke`; parses `application/x-www-form-urlencoded`; delegates to `OAuth2Service`; returns `OAuth2ErrorResponse` for `/token` errors, `ErrorResponse` for introspect/revoke errors - [x] 5.4 Create `src/routes/token.ts` — Express router; `/token` uses no Bearer auth middleware (credentials are in body); `/token/introspect` and `/token/revoke` use `auth` middleware ## 6. Credential Management - [x] 6.1 Create `src/repositories/CredentialRepository.ts` — `create`, `findById`, `findByAgentId` (with pagination + status filter), `updateHash`, `revoke`, `revokeAllForAgent`; all SQL here only - [x] 6.2 Create `src/services/CredentialService.ts` — `generateCredential` (checks agent active status, generates secret via `crypto.ts`, bcrypt-hashes, persists), `listCredentials`, `rotateCredential` (generates new secret, replaces hash, same credentialId), `revokeCredential`; calls `AuditService` for all write operations; JSDoc on all public methods - [x] 6.3 Create `src/controllers/CredentialController.ts` — HTTP handlers for all 4 credential endpoints; Joi validation; delegates to `CredentialService` - [x] 6.4 Create `src/routes/credentials.ts` — Express router under `/agents/:agentId/credentials` with `auth` and `rateLimit` middleware ## 7. Audit Log Service - [x] 7.1 Create `src/repositories/AuditRepository.ts` — `create(event)`, `findById(eventId)`, `findAll(filters, pagination)` with support for `agentId`, `action`, `outcome`, `fromDate`, `toDate` filtering and 90-day retention window enforcement - [x] 7.2 Create `src/services/AuditService.ts` — `logEvent(agentId, action, outcome, ipAddress, userAgent, metadata)` (async insert, fire-and-forget for token endpoints); `queryEvents(filters, pagination)`, `getEventById(eventId)`; enforces 90-day retention on queries; JSDoc on all public methods - [x] 7.3 Create `src/controllers/AuditController.ts` — HTTP handlers for `GET /audit` and `GET /audit/{eventId}`; scope check for `audit:read`; Joi validation of query params - [x] 7.4 Create `src/routes/audit.ts` — Express router with `auth` and `rateLimit` middleware ## 8. Application Assembly - [x] 8.1 Create `src/app.ts` — Express app factory: registers `helmet`, `cors`, `morgan`/`pino-http`, JSON body parser, `urlencoded` body parser (for token endpoints), all 4 route modules, and `errorHandler` middleware; exported function (not called directly — testable) - [x] 8.2 Create `src/server.ts` — imports `app.ts`, reads `PORT` from env, calls `app.listen`; entry point only ## 9. Unit Tests - [x] 9.1 Write unit tests for `src/utils/crypto.ts` — secret generation format, bcrypt hash/verify round-trip - [x] 9.2 Write unit tests for `src/utils/jwt.ts` — sign/verify/decode with RS256 test keys - [x] 9.3 Write unit tests for `src/utils/validators.ts` — valid and invalid inputs for every Joi schema - [x] 9.4 Write unit tests for `src/services/AgentService.ts` — mock `AgentRepository` and `AuditService`; cover all scenarios from agent-registry spec - [x] 9.5 Write unit tests for `src/services/OAuth2Service.ts` — mock `TokenRepository`, `CredentialRepository`, `AuditService`; cover all scenarios from oauth2-token spec - [x] 9.6 Write unit tests for `src/services/CredentialService.ts` — mock `CredentialRepository`, `AgentRepository`, `AuditService`; cover all scenarios from credential-management spec - [x] 9.7 Write unit tests for `src/services/AuditService.ts` — mock `AuditRepository`; cover query, filter, and retention logic - [x] 9.8 Write unit tests for `src/middleware/auth.ts` — valid token, expired token, revoked token, missing header - [x] 9.9 Write unit tests for `src/middleware/errorHandler.ts` — each `SentryAgentError` subclass maps to correct HTTP status and error code ## 10. Integration Tests - [x] 10.1 Write integration tests for Agent Registry (`tests/integration/agents.test.ts`) — all 5 endpoints, all response codes, pagination, filtering; uses real Postgres (test DB) and Redis - [x] 10.2 Write integration tests for OAuth2 Token Service (`tests/integration/token.test.ts`) — all 3 endpoints, all response codes, token issuance and revocation flow, RFC compliance - [x] 10.3 Write integration tests for Credential Management (`tests/integration/credentials.test.ts`) — all 4 endpoints, all response codes, full rotate-then-revoke flow - [x] 10.4 Write integration tests for Audit Log Service (`tests/integration/audit.test.ts`) — query with all filter combinations, single event retrieval, retention window enforcement - [x] 10.5 Verify test coverage meets >80% threshold across all services (`npm test -- --coverage`)