feat(web): split SPA from oikos binary, require auth on every route
Phase 0 of plans/2026-07-12-wails-desktop-app.md. The control-room SPA is no longer embedded (web/embed.go deleted); it's a standalone static build served separately (make ui / make deploy-ui). The api process adds CORS and drops the dev-open auth bypass — every route now needs a real bearer token, including SSE (?token= query param, EventSource can't set headers) and api's own /agent proxy to nomos (previously unauthenticated by omission). nomos was an unauthenticated client of api's /mcp and approval-decision endpoints; closing dev-open would have broken it, so it now sends Authorization: Bearer $OIKOS_MCP_BEARER_TOKEN on every call back to api. SPA gets a runtime config module (config.ts) and a Config.svelte first-launch/reconfigure page, reachable afterwards via a "Connection" entry in the sidebar footer. Every fetch() in api.ts routes through fetchWithAuth so the same build works same-origin (browser prod, Vite dev proxy) or cross-origin (future Wails webview, remote access). Six gaps found against the plan and the live Caddy topology while implementing — documented in the plan's "Plan review" section, most notably: api's own /agent mount was never behind combinedAuth (fixed), and production's Authentik forward-auth needs a bearer-token bypass for API routes that this repo's Caddyfile.oikos reference copy now has, but the real dtoro/caddy-conf deploy does not yet. Verified live: cross-origin static SPA + API, CORS, bearer auth, SSE query-token auth, and localStorage persistence all confirmed working in-browser. Full Go test suite and npm run build pass with no regressions against the pre-change baseline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
31
README.md
31
README.md
@@ -13,18 +13,24 @@ learns from outcomes, and escalates when uncertain.
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# Dev stack (postgres + api + scheduler + notifier)
|
||||
docker compose --profile dev up -d
|
||||
# Dev stack (postgres + api + scheduler + notifier). The api/nomos
|
||||
# services need a shared token — every route requires a real bearer
|
||||
# credential, there's no dev-open bypass.
|
||||
OIKOS_MCP_BEARER_TOKEN=dev-token docker compose --profile dev up -d
|
||||
|
||||
# Full stack (adds Nomos agent gateway)
|
||||
docker compose --profile full up -d
|
||||
OIKOS_MCP_BEARER_TOKEN=dev-token docker compose --profile full up -d
|
||||
|
||||
# Build standalone binary
|
||||
go build -o bin/oikos -tags timetzdata ./cmd/oikos
|
||||
|
||||
# Run all roles in one process (dev mode)
|
||||
OIKOS_DATABASE_URL="postgres://oikos:oikos_dev@localhost:5432/oikos?sslmode=disable" \
|
||||
OIKOS_API_TOKEN=dev-token \
|
||||
go run ./cmd/oikos all
|
||||
|
||||
# Control-room SPA (separate from the Go binary — see web/)
|
||||
cd web && OIKOS_API_TOKEN=dev-token npm run dev # http://localhost:5173
|
||||
```
|
||||
|
||||
## Architecture
|
||||
@@ -66,9 +72,12 @@ Full plan: [plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md](p
|
||||
### API endpoints
|
||||
|
||||
```bash
|
||||
curl http://localhost:8090/api/v1/entities?type=service # fleet
|
||||
curl http://localhost:8090/api/v1/health # fleet health
|
||||
curl http://localhost:8090/api/v1/agent-activity # agent log
|
||||
curl -H "Authorization: Bearer $OIKOS_API_TOKEN" \
|
||||
http://localhost:8090/api/v1/entities?type=service # fleet
|
||||
curl -H "Authorization: Bearer $OIKOS_API_TOKEN" \
|
||||
http://localhost:8090/api/v1/health # fleet health
|
||||
curl -H "Authorization: Bearer $OIKOS_API_TOKEN" \
|
||||
http://localhost:8090/api/v1/agent-activity # agent log
|
||||
```
|
||||
|
||||
### Nomos queries
|
||||
@@ -97,6 +106,15 @@ oikos secret list # enumerate SOPS secrets
|
||||
oikos secret migrate # SOPS → Infisical
|
||||
```
|
||||
|
||||
### Web UI
|
||||
|
||||
`web/` is a standalone Svelte 5 SPA — not embedded in the `oikos` binary, not
|
||||
part of `docker-compose.yml`. It talks to `api`/`nomos` over HTTP with a
|
||||
bearer token entered on first launch (see `web/src/pages/Config.svelte`).
|
||||
Build with `make ui`, deploy with `make deploy-ui` (Caddy serves the static
|
||||
output). A native desktop wrapper is planned — see
|
||||
[plans/2026-07-12-wails-desktop-app.md](plans/2026-07-12-wails-desktop-app.md).
|
||||
|
||||
## Repo layout
|
||||
|
||||
```
|
||||
@@ -105,6 +123,7 @@ cmd/nomos/ Nomos MCP client gateway
|
||||
internal/ Go packages (httpapi, mcp, scheduler, actuator, learning,
|
||||
notifier, policy, secrets, db, config, ontology, domain,
|
||||
knowledge)
|
||||
web/ Control-room SPA (Svelte 5) — standalone, not embedded
|
||||
api/openapi.yaml API contract (OpenAPI 3.1)
|
||||
migrations/ Forward-only SQL migrations (TimescaleDB)
|
||||
seeds/ Bootstrap YAML (ontology, inventory, policy, knowledge)
|
||||
|
||||
Reference in New Issue
Block a user