System Architecture — Multi-App Function Surface
Maps every external consumer of Syntropy Journals, the data they read/write, and the API routes and functions that serve them. Updated: 2026-03-27 | Companion: FUNCTION_TAXONOMY.md, INTEGRATION_SURFACES.md
Consumer Matrix
| Consumer | Auth | Protocols | Check-ins | Health Profile | Diet/Scoring | Chat/AI | Tokens |
|---|---|---|---|---|---|---|---|
| Shopify App | Bearer split-token | Pull: adherence, feedback | Pull: aggregate | — | — | — | — |
| OpenClaw MCP | Clerk JWT (OAuth 2.1) | Pull: subscriptions | Push+Pull | Pull | Pull: score, gap | Push+Pull: chat | Pairing verify |
| Chrome Extension | sh_* API key | — | — | Pull | Push: food, Pull: score | — | Key exchange |
| Mobile (planned) | Clerk JWT | Pull: subscriptions | Push+Pull | Pull | Pull: score | — | Pairing code |
| Web App | Clerk session | Full CRUD | Full CRUD | Full CRUD | Full | Full | Full |
1. Shopify Protocols App
Routes:/api/v1/* | Auth: Bearer split-token | Rate: 60 read, 20 write/min
| Method | Route | Dir | Function |
|---|---|---|---|
| GET | /api/v1/analytics/summary | Pull | get_partner_summary_sync |
| GET | /api/v1/analytics/protocols/{id}/adherence | Pull | get_protocol_adherence_sync |
| GET | /api/v1/analytics/protocols/{id}/feedback | Pull | get_protocol_feedback_sync |
| GET | /api/v1/analytics/protocols/{id}/retention | Pull | get_protocol_retention_sync |
| POST | /api/v1/protocols | Push | create_protocol_sync |
| PUT | /api/v1/protocols/{id} | Push | update_protocol_sync |
| DELETE | /api/v1/protocols/{id} | Push | update_protocol_sync(status=archived) |
shopify-protocols/app/lib/journals-api.ts
2. OpenClaw MCP Server (PRD-20, Planned)
Mount:/mcp | Auth: Clerk JWT via MCP OAuth 2.1
| MCP Tool | Dir | Service Method | Function |
|---|---|---|---|
chat_with_shrine | Push+Pull | ChatService.invoke_agent | ShrineAgent.invoke |
log_food | Push | CheckinService.log_food | create_food_log_sync |
log_checkin | Push | CheckinService.create_checkin | intake_and_process_checkin |
get_diet_score | Pull | DietService.get_score | compute_diet_fulfillment_score |
get_health_profile | Pull | ProfileService.get_health_profile | get_health_profile_sync |
get_health_snapshot | Pull | DietService.get_snapshot | build_health_snapshot |
get_diet_gap | Pull | DietService.get_gap | compute_diet_gap |
get_my_protocols | Pull | ProfileService.get_user_protocols | get_user_protocols_sync |
analyze_food | Pull | DietService.analyze_food | analyze_food_text |
get_my_checkins | Pull | CheckinService.get_checkins | get_checkins_for_user_sync |
3. Chrome Shrine Extension
Routes:/api/ext/*, /api/diet/* | Auth: sh_* API key
| Method | Route | Dir | Function | Client |
|---|---|---|---|---|
| GET | /api/ext/profile | Pull | get_health_profile_sync | JournalApiClient.getHealthProfile() |
| POST | /api/ext/food-log | Push | create_food_log_sync | JournalApiClient.logFood() |
| POST | /api/ext/api-key-exchange | Push | Profile provisioning | JournalApiClient.exchangeClerkTokenForApiKey() |
| POST | /api/ext/diet/analyze | Pull | analyze_food_text | via diet-api.ts |
| GET | /api/ext/diet/score | Pull | compute_diet_fulfillment_score | via diet-api.ts |
| POST | /api/diet/score-food | Pull | DietAgent.score_food | DietApiClient.scoreFoodFit() |
docs/api/openapi.json (CI-enforced via make openapi-check)
4. Syntropy Mobile (Planned)
Routes:/api/ext/* | Auth: Clerk JWT
Reuses extension endpoints. Needs new: POST /api/ext/checkin, GET /api/ext/checkins.
Service Layer Mapping
Every MCP tool maps to a service method which maps to a function:| Service | Methods | Consumers |
|---|---|---|
ChatService | invoke_agent, get_chat_sessions | MCP |
DietService | get_score, get_gap, get_snapshot, analyze_food, recommend_targets | MCP, Chrome, Mobile |
CheckinService | get_checkins, create_checkin, log_food, get_food_logs | MCP, Mobile |
ProfileService | get_user_profile, get_health_profile, ensure_profile_records, get_user_protocols | MCP, Chrome, Mobile |
MCP Deployment Decision
Decision: MCP server is embedded in the main Reflex/FastAPI app, mounted at/mcp.
Rationale: All functions/db_utils/ use rx.session() (Reflex’s SQLAlchemy session factory). Extracting to a standalone app would require replacing ~40 session calls — high effort, high regression risk, zero user value.
Extraction trigger: If MCP traffic exceeds 30% of total requests, or independent scaling is needed, extract functions/ + services/ + mcp/ into a separate syntropy-mcp Railway service. The service layer boundary already enables this — replace rx.session() with a standalone SessionLocal factory.
Current coupling point: functions/db_utils/*.py → rx.session() (Reflex session factory)
Pending Gaps
| Gap | Consumer | Priority |
|---|---|---|
POST /api/ext/checkin | Mobile, MCP | High |
GET /api/ext/checkins | Mobile, MCP | High |
MCP server mount at /mcp | MCP | Phase 4 |
| Symptom reporting endpoint | Chrome | Low |
| Product search endpoint | Chrome | Low |