Architecture#

rackattack is one service core behind four interfaces. gRPC is the primary product contract; REST comes essentially for free via grpc-gateway over the same proto; GraphQL (gqlgen) is a third HTTP transport; and MCP is a thin secondary adapter (built last) that maps the same core to agent tools. All four speak to a single core that does validation, complex filtering, aggregation, and bulk operations, then walks the infra graph and renders the result.

Because every transport resolves through that one core, the cross-cutting concerns — authorization, read caching, change auditing, and metrics/tracing — are applied once, in the wrappers the transports share, rather than per-transport.

Four interfaces, one core with cross-cutting layers, one datastore
Four interfaces, one core with cross-cutting layers, one datastore

Layers#

  • Transports — gRPC (internal/server), REST (grpc-gateway, in-process), GraphQL (internal/graph, gqlgen), and MCP (internal/mcp). They are adapters; they hold no business logic. See API surface.
  • Cross-cutting — applied around the core so all transports share them:
    • Auth (internal/auth) — OIDC/JWT validation at the edge + role-based authorization in a shared Authorizer. See Security & auth.
    • Cache (internal/cache) — a read-through cache (in-process LRU or Redis) over hot reads, flushed on any mutation. See Caching.
    • Audit/CDC (internal/audit) — mutations captured via CockroachDB CHANGEFEED to an audit_log, read back over HTTP. See Audit & CDC.
    • Observability (internal/metrics, internal/telemetry) — Prometheus metrics + OpenTelemetry spans. See Observability.
  • Service core — request validation and ref resolution, complex filtering, aggregation, and single + bulk mutations.
  • Graph + render — recursive/aggregate workloads (blast radius, cable path, thermal) expressed as SQL WITH RECURSIVE, then laid out by Graphviz and painted to SVG.
  • Data accesspgx against CockroachDB.

Request lifecycle#

A single screen-generating call runs end to end: the transport validates and resolves refs, the query layer issues a recursive CTE, CockroachDB returns rows, layout assigns geometry (Graphviz dot -Tjson for relationship graphs, direct grid math for geometric ones), and the painter emits the artifact alongside the structured data.

One screen-generating call, end to end
One screen-generating call, end to end

Why CockroachDB (not Postgres)#

This is the system of record for physical reality across many sites, so the datastore choices are correctness choices:

  • Strong, serializable consistency — you cannot have split-brain about what’s cabled to what or which feed powers which rack.
  • Geo-distributed, survives region/AZ loss — the tooling stays up across the same sites it models.
  • Horizontal scale without manual sharding as the fleet grows.
  • Postgres wire-compatiblepgx, recursive CTEs, and standard SQL all work, so there’s no downside versus Postgres.

See the README for the full rationale.