Skip to main content

ADR-024: Tilt as the canonical local-development orchestrator

Context​

New engineers and coding agents cannot reliably boot the Aucert stack. The golden path lives in tribal knowledge and throwaway /tmp scripts; the committed Tiltfile is an abandoned Day-1 stub pointing at paths that no longer exist; the committed dev docker-compose has the wrong Postgres image and a mis-set worker flag; there is no local auth (Kong is absent, so everyone hand-rolls a proxy); and nothing in CI executes the environment, so it drifts freely until it costs a teammate a day.

Forcing functions and constraints:

  • ADR-002 mandates a native inner loop during MVP — so the daily loop must not require a local Kubernetes cluster.
  • ADR-013 established that "things that must stay true" are enforced by CI/hooks, not discipline. The dev environment must be enforced the same way.
  • Developers are on macOS (Apple Silicon); CI is Linux. The Android emulator cannot run in Docker on macOS (/dev/kvm), so any full-fidelity or device path is platform-specific.

Decision​

Adopt Tilt as the single sanctioned way to run services locally, in native mode: infrastructure (Postgres, Redis, Temporal, dev gateway) in docker compose; application code (backend, console, opt-in rover-worker) as Tilt local_resources — no local Kubernetes in the daily loop. tilt up is the one command for humans; tilt ci is the headless, self-verifying entry for CI and agents.

The environment becomes self-testing: a tilt ci job (on dev-file-touch + nightly) boots the stack, waits for readiness, and runs a smoke test — so drift surfaces as a red build, not a lost afternoon. This same rule binds agents: they start services via tilt up/tilt ci, never bazel run/pnpm dev directly (encoded in AGENTS.md → CLAUDE.md).

Kubernetes-based prod fidelity (kind + Helm + Kong) is on-demand only, materialized from CI-validated charts (helm lint + kubeconform); it is never a standing, maintained environment. The shared Azure dev cluster is the normal fidelity target, reachable by flipping one env target.

The full design, corner cases, and acceptance criteria live in SPEC-052.

Alternatives considered​

OptionProsCons
Tilt (native mode) — chosenone command + dashboard; native inner-loop speed (ADR-002); tilt ci makes it self-testing; one path for humans + agentsa new required tool (Tilt) + Docker; a Tiltfile/compose to maintain (now CI-enforced)
Make/scripts + compose + nativezero new dependency; most portabledumb conductor — no dashboard/health/auto-reload; still needs its own CI executor; misses the "don't babysit / easy debugging" bar
Standing local k8s (kind + Helm + Kong)highest prod fidelityheaviest; slow inner loop (image builds); most rot-prone (few run it → it dies)
Status quo (tribal + /tmp + hand-rolled proxy)nonethe very cause of the problem

Consequences​

What becomes easier​

  • Clone-and-go: one command to a working console; onboarding in minutes.
  • Debugging: one dashboard with per-service logs, health, and restart.
  • Agents (incl. cloud) bring the stack up the same self-verifying way, instead of ad-hoc spawning.
  • A clean, on-demand upgrade path to real k8s/Kong fidelity when genuinely needed.

What becomes harder​

  • One more required install (Tilt) plus Docker.
  • A Tiltfile + compose to keep correct — but CI (tilt ci) now forces that maintenance.
  • The dev gateway is a proxy, not real Kong — a deliberate local-fidelity gap.

Risks​

  • tilt ci adds CI minutes (mitigated: gate on dev-file-touch + nightly, cache Bazel/pnpm).
  • The rover-worker/emulator stays platform-specific (macOS native AVD vs Linux KVM container) — irreducible; contained behind an opt-in profile.
  • If the tilt ci gate is ever disabled, the environment reverts to rotting — the gate is the whole guarantee and must not be treated as optional.