Service Topology: What Actually Runs
sparki beginner 5 min read
ELI5
Sparki used to be drawn as a workshop with six stations. Today only three are switched on: the shop window (web-app), the front desk (api-engine), and a separate locked room where builds run (build-worker). The other stations in the floor plan (an auth desk, a deployer crane, a contract printer, an observability rig) are either retired or were never wired in.
Technical Deep Dive
Source: sparki-tools/api-engine cmd/api/main.go:40-118, pkg/api/server.go:215-354, cmd/build-worker/main.go:1-123, Dockerfile:50-59 @0b0309f; sparki-tools/platform-docs launch/gap-register.md:55, decisions/2026-08-09-retire-auth-shield.md @65a451e; live probe of sparki.tools, my.sparki.tools and api.sparki.tools/health, read 2026-10-25.
Deployed path
| Process | Repo / entrypoint | Host | Holds |
|---|---|---|---|
| web-app | sparki-tools/web-app, Next.js 14 | Vercel (sparki.tools, my.sparki.tools; server: Vercel) | airlock handoff, __app_session cookie, same-origin /api/* rewrite to the engine |
| api-engine | sparki-tools/api-engine, cmd/api (Go, Fiber) | Railway (api.sparki.tools; server: railway-hikari) | Postgres + Redis, airlock session check, TOLL client, worker API |
| build-worker | sparki-tools/api-engine, cmd/build-worker | dedicated VPS (gate G9, not provisioned) | one worker token + the API URL, nothing else |
The Docker image builds only ./cmd/api and ./cmd/migrate (Dockerfile:50-59). The worker is a separate binary. On 2026-10-25 /health answered {"status":"degraded","workers":{"state":"unconfigured"}}: no worker token digests are set, so the worker routes are not registered and queued builds do not run.
flowchart LR B["Browser"] --> W["web-app on Vercel"] T["sparki-tui"] -. "device-code token" .-> A W -- "same-origin /api/* rewrite" --> E["api-engine on Railway"] W -- "OIDC sign-in" --> A["airlock"] E --> PG[("Postgres")] E --> RD[("Redis")] E -- "toll.checkout and toll.entitlements" --> TL["null0-toll"] K["build-worker on VPS"] -- "HTTPS /internal/worker/*" --> E D["DSN Prometheus"] -. "GET /metrics bearer" .-> ENot on the deployed path
flowchart TD S["services/ in sparki-tools"] --> AS["auth-shield: retired 2026-08-09, airlock is sole IdP"] S --> DL["deploy-loco: no route in cmd/api, not deployed"] S --> SM["smithy: no deploy config, last main 2026-08-09"] S --> OS["observability-storm: no deploy config, last main 2026-02-24"] S --> BF["build-forgery: no code, last main 2026-03-12"] E2["api-engine subsystems/"] --> NL["present on main, not linked into cmd/api or cmd/build-worker"]There is no message broker on the deployed path. internal/mq (RabbitMQ, amqp091-go) is still in the tree, but only internal/service imports it and nothing reachable from cmd/api or cmd/build-worker imports internal/service. The build queue is the builds table itself (sparki-004).
Key Terms
- api-engine → the Go/Fiber API; the only backend process in production.
- build-worker → the separate binary that claims builds over HTTPS and runs each step in a container.
- G9 → the launch gate “build worker VPS provisioned and verified”; open on 2026-10-25.
__app_session→ the apex-local session cookie the web app mints after airlock sign-in; the engine verifies it.
Q&A
Q: Which three processes are on the deployed path, and where does each run? A: web-app on Vercel, api-engine on Railway, and build-worker on a dedicated VPS. The VPS has not been bought yet (G9), so the worker is designed and coded but not running.
Q: Which services in services/ have no deployment, and what replaced auth-shield? A: auth-shield (retired by ADR 2026-08-09), deploy-loco, smithy, observability-storm and build-forgery. airlock replaced auth-shield as the only identity provider.
Q: How does a build step get from a queued build row to a container?
A: POST /api/v1/builds inserts a pending row; a worker claims it with POST /internal/worker/claim, then runs each step in its own sandboxed container and reports logs and the result back over HTTPS (sparki-004, sparki-018, sparki-019).
Examples
A user clicks Run on my.sparki.tools. The browser calls /api/v1/builds on its own origin; Vercel’s fallback rewrite forwards it to api.sparki.tools with the session cookie; the engine checks the plan through TOLL, inserts a pending build and returns 201. Until a worker token is configured, that build stays pending and /health reports degraded once it has waited five minutes.
neighbors on the map
- Three-Tier Architecture (Core → Choco → MERIDIAN) explaining the deployment model