Skip to content

2026-05-09 — petrova.host v0 launch (Fleet MCP server live on Railway)


rank: decision outranks: [finding, runbook]

Section titled “rank: decision outranks: [finding, runbook]”

2026-05-09 — petrova.host v0 launch (Fleet MCP server live on Railway)

Section titled “2026-05-09 — petrova.host v0 launch (Fleet MCP server live on Railway)”

Date: 2026-05-09 Status: closed Supersedes: none Superseded-by: none — current

PRs #36 (spec), #37 (plan) and #38 (implementation, Tasks 1–16) shipped the v0 read-only Fleet MCP server. This decision records the Task 17 deploy: Railway service, env wiring, bearer rotation, and the §8 acceptance state of the v0 spec.

  • JSON-RPC: https://petrova-host-production.up.railway.app/rpc
  • Custom domain (pending DNS cutover): https://petrova.host/rpc — added to the Railway service; petrova.host is currently parked at dns-parking.com (Namecheap default). DNS cutover is a manual registrar step. CNAME target: 6x4uohnb.up.railway.app.
  • Railway project: petrova-host (workspace: Devarno, project id 9b1073fb-30ca-4d29-b3ee-55ae409d845d).
  • Build: Dockerfile at repo root. Build context = repo root so the image bundles registry.yaml, state/, docs/decisions/, and contracts/ alongside the host build. Eva and Grace use the v0 fixture mini-trees from host/tests/fixtures/. KAHN points at https://kahn.example.com (stub — no live KAHN Scope API yet).
  • Restart policy: ON_FAILURE. Healthcheck path is omitted on purpose because GET /rpc returns 404 (the server only handles POST /rpc); Railway’s port-listen check suffices for v0.
VarValue
PETROVA_HOST_BEARER(rotation: see below; stored in Railway secrets)
PETROVA_HOST_REGISTRY_PATH/app/petrova
PETROVA_HOST_EVA_PATH/app/eva
PETROVA_HOST_GRACE_PATH/app/grace
PETROVA_HOST_KAHN_APIhttps://kahn.example.com (stub)
PETROVA_HOST_SHARDglobal
LOG_LEVELinfo
  • The global-shard bearer is generated with openssl rand -base64 32 and stored in (a) Railway env var PETROVA_HOST_BEARER and (b) the operator’s password manager under “petrova.host global shard bearer”.
  • Rotation cadence: every 90 days, or immediately on suspected leak.
  • Rotation procedure: generate a new value, set it in Railway, redeploy the service, then update consumer repos that hold the bearer (currently only the eva-hq canary script, once Task 18 lands).

contracts/petrova.host.consumption.v0.yaml — pins each upstream source adapter to a specific contract version. Bundled into the image at /app/contracts/; loaded at boot (the boot log shows consumption_profile: "loaded").

  • §8.1 — tools/list returns 11 → satisfied (smoke-tested on the live URL; integration test in host/tests/integration/server.test.ts).
  • §8.2 — petrova.context for petrova-codes returns a valid bundle → satisfied (live smoke confirmed: 19 fleet repos in registry.query, real decision docs from decisions.search).
  • §8.3 — Bundle assembled for ≥3 real slugs → satisfied for the cardinality (registry has 19 slugs, all queryable; specific slug-by- slug audits remain a follow-up runbook).
  • §8.4 — HTTPS twin same surface as MCP → satisfied (5 integration tests in host/tests/integration/server.test.ts; live deploy uses the HTTPS twin exclusively).
  • §8.5 — Launch decision doc → this doc.
  • §8.6 — Canary migration of eva-hq’s CLAUDE.md to boot from petrova.context()satisfied (eva-hq#13 merged 2026-05-09). eva-hq had no prior CLAUDE.md; the canary created one whose first instruction is bash scripts/petrova-context.sh. End- to-end verified against the live Railway URL — script returns a real bundle with 10 fleet neighbours and 5 recent decisions.
  • State schema mismatch: governance.phase returns null for some slugs because the existing state/<slug>.yaml files use a current_status field instead of the phase.{current,status,…} shape this server expects. Out of scope for v0 (host code is correct against the spec; the data files predate the spec). v1 work will normalise.
  • Eva/Grace data: the deploy bundles fixture mini-trees, not the real eva-hq and grace-hq working trees. Real upstreams attach via mounted volumes + sidecar fetch in v1.
  • KAHN: stub URL, returns empty transitions. Real wire-up lands once KAHN Scope deploys publicly.
  • DNS cutover: petrova.host CNAME is on the operator’s TODO; the Railway custom domain is pre-registered with target 6x4uohnb.up.railway.app.
  • Plan’s degraded smoke deploy (skip path env vars, server crash-loops on boot, smoke just confirms 401) — rejected: useless for the eva-hq canary, since petrova.context would never return real data.
  • Bundle test fixtures only — rejected: same reason, fake data defeats §8.6’s purpose.
  • Defer deploy to v1 — rejected: §8 is the v0 acceptance gate and §8.5 requires this doc.
  • Real federation queries against the live URL work today against this repo’s data (registry, state, decisions). Eva/Grace queries return fixture data until v1.
  • Anyone with the bearer can read the full fleet registry + every decision doc. That’s by design — this content is open-source already — but the bearer keeps the API off public crawlers and rate-limit floors.
  • Once §8.6 closes, eva-hq becomes the first consumer with a hard runtime dependency on https://petrova.host/rpc. Outages (Railway, DNS, expired bearer) will degrade eva-hq sessions — its CLAUDE.md fallback block keeps the failure mode degraded-not-dead.