# Chapter 7 — Deployment and operations

*How the system runs in production, how releases move, and what the operator actually
does. The deliberate headline: this is a **small estate run with big-estate
discipline** — one VM, Compose, Caddy — governed by migration gates, provenance
ledgers, and runbooks rather than by fleet machinery it does not need yet.*

## 7.1 The production estate

The deployment target is recorded as an ADR, not folklore (ADR-GO-015): Docker Compose
on a single cloud VM behind Caddy, with Cloudflare in front. The public surfaces:

| Surface | What it serves |
|---|---|
| `rosetta-design.com` | The console (enablement agent): registration, keys, engagements, governance views, admin; the KMS-gated install/download routes |
| `api.rosetta-design.com` | RGAS — the versioned REST API (canonical API hostname since the DT-RX-026 domain consolidation) |
| `mcp.rosetta-design.com` | The hosted MCP connector (streamable HTTP + OAuth) |
| `docs.rosetta-design.com` | The public docs build; `/internal/` is the insiders build behind an auth gate |

The graph (Neo4j) and MySQL run on the same estate; Caddy terminates TLS and
health-checks RGAS's `/health`, which reports healthy only when both stores answer.
Infrastructure is Terraform in the producer repo (VPC, VPN, firewall, disks,
snapshots) — the estate is declared, not hand-built, and infrastructure ownership
itself has a governance trail (an early misalignment over which repo owned the VM was
resolved by a ratified divestment DT).


## 7.2 The migration lane

Production data changes ride **governed lanes only** — an explicit operating rule, not
a habit. The composed producer lane (`make prod-migrate`) chains: schema apply → seed
load → engagement-stack load → the serial invariant gates (all 39 INV-D checks; a
red gate stops the train) → API registration → a `ProvenanceEvent` ledger entry
recording the migration itself. MySQL migrations are idempotent and numerically
ordered, re-runnable on a fully-applied database by construction, and CI re-runs them
to prove it. The design consequence an assessor should note: **a production migration
cannot silently skip its own verification**, and every one leaves a graph-visible
record.

## 7.3 Release trains and the re-vendor chain

A constellation of pinned contracts means releases are *trains*, not events. The
canonical sequence when the producer cuts a release: platform tags and publishes two
sibling artifacts (the consumer intake tarball and the KMS-gated install bundle);
the app server re-pins its build-time intake and tags; the MCP server re-vendors the
OpenAPI contract, regenerates wrappers (the tool-policy completeness guard forcing a
conscious decision on any new tag), tags, cross-compiles, and byte-verifies the
published binaries; the console re-vendors the download channels. The umbrella's
compat matrix records what shipped together, and `make versions` flags pin drift.

The discipline is real and the record shows it working — and also shows its cost:
at snapshot the MCP re-vendor train is mid-flight (main vendors the new contract;
tag and binary publish pending), and three matrix rows lag observed reality. The
release machinery is strong; the *bookkeeping around it* is manual and behind
(Chapter 10, finding cluster B).

## 7.4 Observability

Three layers, each owned in the right place:

- **Runtime logs** ship to the estate log aggregator (documented and dashboarded from
  the sysops member, which owns the cross-estate view).
- **LLM/trace observability** is Arize Phoenix, deployed by the producer repo's
  compose (deployment authority stays with the platform; sysops documents the
  operator path), with OTLP collectors declared by ADR and dashboards checked into
  the repo.
- **API-key audit** is asynchronous and structural in RGAS (every authenticated
  request audited to a MySQL table), separate from logs.


## 7.5 CI and the runner estate

Both core repos run path-filtered CI behind a single required `all-green` check, with
the mutual-exclusion trick (a paths-ignore twin workflow) keeping the required check
present even on PRs that touch nothing CI-relevant. The jobs worth an assessor's
attention are the ones that load real databases: schema smoke, seed smoke,
migration-idempotency re-runs, the invariant gates, corpus replay against a live
stack, and an installer smoke that exercises the *published* distribution route with
a real scoped key — CI that tests the delivery mechanism, not just the code.


## 7.6 Operational surface discipline

The rule that makes the whole chapter auditable: **`make` is the operational surface**
(ADR-PL-004). Every operation — migrations, backups, seed loads, invariant runs,
bundle publishes, deploys — has a make target delegating to a category-organized,
shellcheck-gated script; raw `docker exec` / `mysql` / `cypher-shell` invocations are
banned from docs and runbooks. For an incoming operator this means the platform
`Makefile` (98 targets, `make help` indexed) *is* the operations manual, and the
runbooks under `docs/runbooks/` cover the lanes that cross machines (release cut,
remote graph ops, content-author checklist).

*Security and tenancy next: [Chapter 8](08-security-tenancy.md).*
