Files
tiny-forge/plans/docker-watcher-core/phase-8-api-layer.md
T
alexei.dolgolyov 97d4243cfe feat(docker-watcher): phase 8 - REST API layer
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.
2026-03-27 22:06:57 +03:00

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, middleware
  • internal/api/projects.go — project CRUD handlers
  • internal/api/stages.go — stage CRUD handlers
  • internal/api/instances.go — instance lifecycle handlers
  • internal/api/deploys.go — deploy + quick deploy handlers
  • internal/api/registries.go — registry CRUD + test + tags handlers
  • internal/api/settings.go — settings handlers
  • internal/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 server
  • server.Router() returns a chi.Router with 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}/logs returns 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_password and webhook_secret, returns has_npm_password boolean
  • Registry list response strips tokens, returns has_token boolean
  • CORS allows all origins (dev mode) -- restrict in Phase 12