97d4243cfe
All REST endpoints wired with chi router: projects, stages, instances, deploys, registries, settings, quick deploy, webhook. Full main.go wiring with graceful shutdown. Consistent JSON envelope responses. Sensitive fields stripped from API responses.
5.7 KiB
5.7 KiB
Phase 8: REST API Layer
Status: ✅ Complete Parent plan: PLAN.md Domain: backend
Objective
Wire up all REST API endpoints using chi router, connecting the store, deployer, and other services to HTTP handlers.
Tasks
- Task 1: Set up chi router with middleware (logging, recovery, CORS, JSON content-type)
- Task 2: Implement project endpoints — GET/POST /api/projects, GET/PUT/DELETE /api/projects/:id
- Task 3: Implement stage endpoints — POST /api/projects/:id/stages, PUT/DELETE /api/projects/:id/stages/:stage
- Task 4: Implement instance endpoints — GET /api/projects/:id/stages/:stage/instances, POST (deploy), DELETE (remove)
- Task 5: Implement instance control endpoints — POST .../instances/:iid/stop, start, restart
- Task 6: Implement quick deploy endpoints — POST /api/deploy/inspect, POST /api/deploy/quick
- Task 7: Implement registry endpoints — GET/POST /api/registries, PUT/DELETE /api/registries/:id, POST .../test
- Task 8: Implement settings endpoints — GET/PUT /api/settings, GET /api/settings/webhook-url, POST .../regenerate
- Task 9: Implement deploy history endpoints — GET /api/deploys, GET /api/deploys/:id/logs (SSE stub)
- Task 10: Implement registry tags endpoint — GET /api/registries/:id/tags/:image
- Task 11: Wire webhook handler into router — POST /api/webhook/:secret-uuid
- Task 12: Wire everything in main.go — initialize all services, start HTTP server
Files to Modify/Create
internal/api/router.go— chi router setup, middlewareinternal/api/projects.go— project CRUD handlersinternal/api/stages.go— stage CRUD handlersinternal/api/instances.go— instance lifecycle handlersinternal/api/deploys.go— deploy + quick deploy handlersinternal/api/registries.go— registry CRUD + test + tags handlersinternal/api/settings.go— settings handlersinternal/api/middleware.go— middleware (logging, CORS, recovery)internal/api/response.go— consistent API response helpers (envelope format)cmd/server/main.go— full service wiring and HTTP server start
Acceptance Criteria
- All endpoints from the API spec in PLAN.md are implemented
- Consistent JSON envelope response format (success, data, error, metadata)
- CORS configured for frontend dev (localhost origins)
- Proper HTTP status codes (200, 201, 400, 404, 500)
- main.go starts a fully wired HTTP server
Notes
- Response envelope:
{"success": bool, "data": any, "error": string|null, "meta": {pagination}} - CORS: allow all origins in dev, restrict in production (configurable later)
- SSE for deploy logs is a stub in this phase — real implementation in Phase 11
- Quick deploy: /inspect pulls and inspects image, returns defaults; /quick creates project + deploys
- All handlers should validate input and return 400 for bad requests
Review Checklist
- All tasks completed
- All API endpoints from PLAN.md are covered
- Consistent response format across all endpoints
- Input validation on all POST/PUT handlers
- No business logic in handlers (delegates to services)
Handoff to Next Phase
API Surface
api.NewServer(store, docker, deployer, webhookHandler, encKey)creates the serverserver.Router()returns achi.Routerwith all routes mounted under/api- Response envelope:
{"success": bool, "data": ..., "error": "..."}
Endpoints Implemented
| Method | Path | Handler |
|---|---|---|
| GET | /api/projects | listProjects |
| POST | /api/projects | createProject |
| GET | /api/projects/{id} | getProject (includes stages) |
| PUT | /api/projects/{id} | updateProject |
| DELETE | /api/projects/{id} | deleteProject |
| POST | /api/projects/{id}/stages | createStage |
| PUT | /api/projects/{id}/stages/{stage} | updateStage |
| DELETE | /api/projects/{id}/stages/{stage} | deleteStage |
| GET | /api/projects/{id}/stages/{stage}/instances | listInstances |
| POST | /api/projects/{id}/stages/{stage}/instances | deployInstance |
| DELETE | /api/projects/{id}/stages/{stage}/instances/{iid} | removeInstance |
| POST | .../instances/{iid}/stop | stopInstance |
| POST | .../instances/{iid}/start | startInstance |
| POST | .../instances/{iid}/restart | restartInstance |
| GET | /api/deploys | listDeploys |
| GET | /api/deploys/{id}/logs | getDeployLogs (JSON stub) |
| POST | /api/deploy/inspect | inspectImage |
| POST | /api/deploy/quick | quickDeploy |
| GET | /api/registries | listRegistries |
| POST | /api/registries | createRegistry |
| PUT | /api/registries/{id} | updateRegistry |
| DELETE | /api/registries/{id} | deleteRegistry |
| POST | /api/registries/{id}/test | testRegistry |
| GET | /api/registries/{id}/tags/* | listRegistryTags |
| GET | /api/settings | getSettings |
| PUT | /api/settings | updateSettings |
| GET | /api/settings/webhook-url | getWebhookURL |
| POST | /api/settings/regenerate | regenerateWebhookSecret |
| POST | /api/webhook/{secret} | webhook handler (mounted from webhook package) |
main.go Wiring
- All services initialized: store, docker, npm, deployer, health, notifier, webhook, poller
- HTTP server with graceful shutdown on SIGTERM/SIGINT
- Environment variables:
DATA_DIR,SEED_FILE,ENCRYPTION_KEY,NPM_URL,POLLING_INTERVAL,LISTEN_ADDR - Default listen address:
:8080
SSE Stub
GET /api/deploys/{id}/logsreturns logs as JSON array (not SSE yet)- Real SSE streaming deferred to Phase 11
Security Notes
- Registry tokens are encrypted before storage, decrypted on read for API calls
- Settings response strips
npm_passwordandwebhook_secret, returnshas_npm_passwordboolean - Registry list response strips tokens, returns
has_tokenboolean - CORS allows all origins (dev mode) -- restrict in Phase 12