phase 2 (part 1): OpenAPI-generated API server, first 9 endpoints

- api/openapi.yaml converted 3.1 → 3.0.3 (oapi-codegen/kin-openapi
  supports 3.0; nullable syntax + example keywords), still redocly-clean
- oapi-codegen (v2.4.1, strict server + chi) generates
  internal/httpapi/gen from the spec; `make generate` wired
- internal/httpapi: chi router, /healthz (unauthenticated, SG18),
  RFC 9457 problem+json mapping from domain sentinels (SG11), 5xx detail
  logged server-side only, request logging with request IDs, graceful
  shutdown (SG4), interim static bearer auth (constant-time; dev-open
  when no token; OIDC JWT still to come in Phase 2)
- Implemented: listEntities (type filter walks the hierarchy, keyset
  pagination), getEntity (UUID or slug, ETag), getEntityRelations,
  getBlastRadius, getGraph (nodes+edges for UIs), getOntology,
  listSignals, getFleetHealth, exportSeeds. Remaining 38 ops return 501
  problem+json stubs (compiler-enforced interface completeness)
- `oikos api` role live: migrate-on-start, serves :8090
- 15 API integration tests (auth, pagination, hierarchy filter, ETag,
  404/501 problem shapes, graph, export)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 08:25:19 +02:00
parent 1b04683639
commit f2fe812cda
13 changed files with 10888 additions and 807 deletions

View File

@@ -17,7 +17,8 @@ type Config struct {
APIListen string // :8090
APIEnv string // dev, prod
// MCP
// Auth (interim Phase 2: static bearer tokens; OIDC JWT later)
APIToken string // operator/CI bearer token for the REST API
MCPBearerToken string // shared secret for Hermes→API MCP calls
// Observability
@@ -54,6 +55,9 @@ func FromEnv() Config {
if v := os.Getenv("OIKOS_ENV"); v != "" {
c.APIEnv = v
}
if v := os.Getenv("OIKOS_API_TOKEN"); v != "" {
c.APIToken = v
}
if v := os.Getenv("OIKOS_MCP_BEARER_TOKEN"); v != "" {
c.MCPBearerToken = v
}