The boundary that keeps Pantheon (fleet) and client workloads walled off on shared Railway + fleet vault. The predicate the pilot, MCP migration, and client retro-fit all enforce.
Pantheon and client (Viska, future clients) workloads share one Railway account and one fleet vault. This spec defines the boundary so a client never rides the fleet's auth surface, secrets never bleed across tenants, and one tenant's compromise cannot reach another. Today the boundary is implicit — Viska is live, but isolation is convention, not rule. This makes it explicit, checkable, ratifiable.
In scope: Railway projects · tokens · secrets · auth · DB connections for hosted MCP + Mastra agents. Out of scope: n8n (VPS) · vault/fabric/obs (N5) · browser-debug (ride-local).
A tenant is an isolation boundary, not a workload. Tenant MUST be readable from the Railway project name. One project per (tenant, service-group). Client tenants are siblings, never nested under Pantheon.
Shared fleet. e.g. pantheon-metis-agent. Auth principal: fleet OAuth client(s).
Per customer. e.g. client-viska-*. Auth principal: per-client OAuth client.
RAILWAY_TOKEN (#194) is admin-plane provisioning only — never embedded in a deployed service./mcp URL across tenants. OAuth 2.1 + PKCE per launch standard.DATABASE_URL shadowing — declare DB var explicitly (e.g. APP_DATABASE_URL), don't rely on platform-injected.The pattern holds iff, for a single compromised tenant (leaked token OR bearer OR service), every line is true. Every new Railway service PR runs this checklist.
Fail any line → non-conformant, does not ship (Phase-2 ratification gate).
RAILWAY_TOKEN not in session (#194). This rests on fleet_services + audit §6/§9, not a live config dump. Conformance below is expected, verified in Phase 4 (#203).
| Service | Tenant | Expected vs pattern | Verify |
|---|---|---|---|
viska-mimir-agent LIVE | client | naming drifts (no client-viska-* prefix); token/secret/auth scope unconfirmed | #203 |
mimir-chat-api LIVE | client | per-client Bearer secret ✓ (named); project-scope unconfirmed | #203 |
pantheon-metis-agent pilot | pantheon | born conformant — built to this doc | #197 |
mastra-bridge MCP | pantheon | deploy + auth unconfirmed | #201 |
Known drift → Phase 4 (#203), additive / no downtime: (a) Viska naming predates the prefix rule; (b) DATABASE_URL shadowing/naming-drift (audit §9); (c) live-client token/secret/auth scoping never audited.
| Phase / issue | Uses the pattern to… |
|---|---|
| 1 · pilot #197 | build pantheon-metis-agent conformant from birth — the reference instance |
| 2 · ratify #200 | sign this doc off as the standard; athena if it becomes a fleet rule |
| 3 · migrate #202 | place each lifted MCP in the correct tenant project under §1–§5 |
| 4 · Viska harden #203 | measure live-client drift against §7 and remediate to conformance |
| 5 · ops #204 | blast-radius checklist (§6) becomes a standing audit item |
Review hook: any new Railway service PR runs the §6 checklist; any cross-tenant secret/token/auth reuse = CHANGES_REQUESTED.
~/.claude/rules/ entry.client-<name>-* scale to N clients on one account, or does a 2nd client warrant a separate Railway account? (blast-radius vs cost)