feat(api): damascus-api FastAPI service on :9110 (P2) #18
Reference in New Issue
Block a user
Delete Branch "feat/entry-points-api"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the P2 deliverable from the entry-points contract.
Endpoints (10 of 10)
Cross-cutting
Compose
Tests: 46 pass against live Postgres
Acceptance (live :9110)
Existing P1 deliverables (api_schemas.py, contract wiki page) untouched.
Implements wiki/concepts/entry-points-contract.md sections 2 + 4: - All 10 endpoints wired to existing state.* helpers (no new mutations): GET /healthz, /v1/items, /v1/items/{id}, /v1/issues, /v1/events, /v1/cost, /v1/stats POST /v1/items, /v1/items/bulk, /v1/issues/{id}/answer - Token check middleware on writes (POST). Empty DAMASCUS_API_TOKEN at startup fails closed (serve_cmd exits 1 before importing api). - Token-bucket rate limit per source IP, default 30/min write + 120/min read, configurable via env. Returns 429 + Retry-After. - psycopg_pool.ConnectionPool(min=2, max=5) shared across FastAPI threadpool (lazy, env-driven). - StaticFiles mount for UI bundle at /opt/damascus/ui; does not crash if the dir is empty (P4 ships this). - 'damascus serve' CLI subcommand with --reload for dev. docker-compose: new damascus-api service reuses the existing damascus-orchestrator image, mounts /opt/damascus/ui from ./ui-bundle (empty dir is fine), reads /root/.hermes/.env for the token, depends on db, healthchecks /healthz. Tests (46 pass against live Postgres at 127.0.0.1:5432): - tests/api/test_api_auth_and_ratelimit.py (auth, 401, 429, /healthz) - tests/api/test_api_endpoints.py (every endpoint, all happy/error paths) - tests/contract/test_api_schemas_match_db.py (enum parity + 3 POST response shape round-trips through real upsert_story + read-back) Acceptance (live compose service at :9110): - healthz -> 200 '{"status":"ok"}' - POST /v1/items no token -> 401 unauthorized - POST /v1/items wrong token -> 401 unauthorized - POST /v1/items correct token -> 200 - 31st POST in 60s from same IP -> 429 with Retry-After - /openapi.json exposes all 10 expected pathsPull request closed