Repo Separation & Access Model¶
Two repositories, two access tiers, one clean boundary.
The Model at a Glance¶
| Repo | What it owns | Access tier |
|---|---|---|
christensen-digital/relay-platform |
MCP server, REST API, database, auth, billing, admin console, all server-side infrastructure | ๐ด Restricted โ EC + select platform keyholders |
christensen-digital/relay-app |
Web app, mobile app, Slack bot, shared client types, design tokens | ๐ก Broader โ platform team + app contributors |
The rule: App contributors have relay-app access only. No app contributor gets relay-platform access โ not even read. Platform keyholders may contribute to both.
What Each Repo Owns¶
relay-platform (restricted)¶
Everything that runs server-side or touches data directly:
- MCP server (
mcp.relayctx.com) โsrc/relay/mcp/โ all tool definitions, nudges, manicure, display - REST API (
api.relayctx.com) โsrc/relay/app.py,routes/,handlers/,services/ - Database layer โ
src/relay/db.py,migrations/โ all SQL queries, schema - Auth, billing, legal, storage โ
src/relay/auth.py,billing.py,legal.py,storage.py - Server-side integrations โ Stripe, SendGrid, Freshdesk, Dub (
src/relay/integrations/) - Notification delivery โ
src/relay/channels/(email, push, Slack notify, web) - Admin console (
console.relayctx.com) โrelay-console/(TypeScript/Vite, operator-only surface) - Deployment config โ
Dockerfile,deploy/(systemd),.github/workflows/
relay-app (broader access)¶
Everything user-facing that consumes platform tooling:
- Web SPA (
app.relayctx.com) โweb/โ TypeScript, Vite, no framework - Mobile app โ
mobile/โ Expo 51, React Native, Expo Router - Slack bot โ
integration-slackbranch โslack/once extracted - Shared types + API client โ
shared/โ typed fetch client, all domain types - Design system tokens โ
packages/ui/โ CSS-only, no JS
Edge Cases & Decisions¶
Admin console stays in relay-platform.
relay-console/ is an internal operator tool tightly coupled to admin API routes that only platform keyholders should touch. Keeping it in the platform repo enforces that access naturally. It is not a user-facing surface.
Slack bot belongs in relay-app.
The Slack integration is a user-facing surface that calls platform MCP tools via API โ same pattern as the web and mobile apps. It belongs in relay-app.
Marketing/landing web assets in platform (short-term).
web/relayctx/ serves static HTML from the same server as the API. Fine for now; candidate for extraction to its own repo if the landing site grows significantly.
How App Talks to Platform¶
App code communicates with platform exclusively over the public API surface:
| Channel | Endpoint | Used for |
|---|---|---|
| REST API | https://api.relayctx.com |
Auth, transfers, series, orgs, billing, user management |
| MCP server | https://mcp.relayctx.com |
All MCP tool calls (relay_transfer_create, relay_pulse_active, etc.) |
No app code imports from platform. No shared module. No monorepo link. No direct database access. The boundary is enforced structurally โ separate repositories with separate deploy pipelines.
Access Model¶
relay-platform relay-app
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
Tier Restricted Broader
GitHub teams platform-core platform-core
app-contributors
Who EC + ~3 platform Platform team +
engineers max app contributors
Deploy path GitHub Actions only GitHub Actions only
(never SSH to server)
Enforcement rules:
- The
app-contributorsGitHub team has access torelay-apponly โ never add torelay-platform. - Any new contributor touching web/mobile/Slack:
relay-apponly. - Any new contributor touching MCP server, API, or DB: requires platform keyholder vetting before any repo access.
- If you're unsure which repo a piece of work belongs in โ if it runs server-side or touches data, it's platform; if it's consumed by an end user or operator UI, it's app.
Branch & Deploy Rules (Both Repos)¶
- Never push directly to
main. Every push tomainauto-deploys to production. - All changes go via branch โ PR โ review โ merge.
- Each distinct change gets its own branch off
mainโ don't pile onto an existing feature branch. - Always syntax-check before anything that could reach the server:
python3 -m compileall -q src/relay/
Platform Cleanup Items¶
The Jun 2026 audit identified these minor housekeeping items in relay-platform โ none are boundary violations, all are internal tidiness:
| Item | Path | Action |
|---|---|---|
| Shadow module directory | platform/relay/ |
Remove โ legacy layout, not part of installed package |
| Consent JS duplication | relay-consent.js (root), relay-console/relay-consent.js |
Delete both; canonical is src/relay/static/consent.js |
| Patch script at root | patch_restore_rich_card_display.py |
Move to scripts/ or archive/ once applied |
| CF Pages worker | cf-pages-notify.worker.js |
Move to .github/ |
relay-app is clean โ no boundary violations. Root-level Python patch scripts (patch_entity_prefixes.py etc.) are one-off migration helpers from the monolith-to-Vite TS transition; remove once applied.
Last updated: 2026-06-14 ยท Audit: relay-platform + relay-app