Files
hermes-mcp/product/incubation/architecture-system.puml
Garfield 8d62e4d9d5 feat: multi-tenant credential isolation + architecture docs
- Add src/multitenancy/ with AES-256-GCM credential store, WhatsApp
  webhook router (phone_number_id -> customerId), and per-customer
  audit log (90-day Redis TTL)
- Add src/billing/ with plan definitions and meterMiddleware that
  resolves API key -> Customer object with getCredential() closure
- Refactor all src/clients/* to accept optional customer param,
  falling back to env vars for backward compat with single-user mode
- Thread customer through handleToolCall(name, args, customer?)
- Add customers table to MySQL schema initDatabase()
- Add /webhook/whatsapp (immediate 200 + async routing) and
  /api/connect/* onboarding endpoints to index.ts
- Add Redis 7 to docker-compose.yml; add REDIS_URL and
  CREDENTIAL_ENCRYPTION_KEY to hermes-k8s.yaml
- Add product/incubation/ with architecture write-up and PlantUML
  diagrams (system architecture + 5 user flows)
- Extend OpenAPI spec in manifest.ts with all platform endpoints

Verification: 3 isolation tests (credential, webhook routing, audit
log) passed against live Redis. Deployed to hermes.squaremcp.com.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 11:27:29 -04:00

160 lines
4.3 KiB
Plaintext

@startuml hermes-mcp-architecture
skinparam backgroundColor #1a1a2e
skinparam defaultFontColor #e0e0e0
skinparam defaultFontSize 13
skinparam arrowColor #888888
skinparam roundCorner 8
skinparam shadowing false
skinparam component {
BackgroundColor #16213e
BorderColor #0f3460
FontColor #e0e0e0
ArrowColor #888888
}
skinparam package {
BackgroundColor #0d1b2a
BorderColor #2a4a6a
FontColor #aaaaaa
FontStyle bold
}
skinparam database {
BackgroundColor #0f2040
BorderColor #533483
FontColor #e0e0e0
}
skinparam cloud {
BackgroundColor #1a0d2e
BorderColor #e94560
FontColor #e0e0e0
}
skinparam note {
BackgroundColor #0d1b2a
BorderColor #2a4a6a
FontColor #aaaaaa
}
title hermes-mcp -- System Architecture (2026-05-08)
' ── AI Clients ────────────────────────────────────────────────────
package "AI Clients" {
[Claude.ai\nMCP connector] as claude
[ChatGPT\ncustom GPT] as chatgpt
[opencode / Codex] as opencode
}
' ── hermes-mcp server ─────────────────────────────────────────────
package "hermes-mcp | Node.js / TypeScript | hermes.squaremcp.com" {
package "Transports" {
[Streamable HTTP\n/mcp] as mcp_t
[SSE legacy\n/sse] as sse_t
[REST API\n/api/*] as rest_t
[Webhook\n/webhook/whatsapp] as wh_t
}
package "Auth" {
[requireAuth\nMCP_API_KEY + OAuth Bearer] as req_auth
[meterMiddleware\nAPI key -> Customer] as meter
[OAuth 2.0\n/oauth/*] as oauth
}
package "Core" {
[handleToolCall\nname, args, customer?] as dispatch
}
package "Platform Clients src/clients/*" {
[whatsapp.ts] as c_wa
[linkedin.ts] as c_li
[telegram.ts] as c_tg
[discord.ts] as c_dc
[instagram.ts] as c_ig
[twitter.ts] as c_tw
[obsidian.ts] as c_ob
}
package "Multi-tenancy src/multitenancy/*" {
[credential-store\nAES-256-GCM] as cred_store
[webhook-router\nphone_id -> customerId] as wh_router
[audit-log\n90-day per-customer trail] as audit_log
}
package "Billing src/billing/*" {
[middleware.ts\nCustomer + meterMiddleware] as billing
[plans.ts\nfree/starter/growth/enterprise] as plans
}
}
' ── Storage ───────────────────────────────────────────────────────
database "Redis 7" as redis
note right of redis
creds:{cid}:{platform} (AES-256-GCM encrypted)
wa_phone_id:{phoneId} (-> customerId)
customer:apikey:{key} (60s TTL cache)
logs:{cid}:{date}:{seq} (90-day audit trail)
end note
database "MySQL 8\nhermes_oauth" as mysql
note right of mysql
customers (id, api_key, plan, active, email)
oauth_clients / oauth_auth_codes / oauth_tokens
end note
' ── Platform APIs ─────────────────────────────────────────────────
cloud "External Platform APIs" {
[Meta Graph API\nWhatsApp + Instagram] as meta_api
[LinkedIn API v2] as li_api
[Telegram Bot API] as tg_api
[Discord API v10] as dc_api
[Twitter API v2] as tw_api
[Obsidian Vault\nfilesystem] as ob_vault
}
' ── Connections ───────────────────────────────────────────────────
claude --> mcp_t : MCP / Bearer
chatgpt --> mcp_t : MCP / Bearer
opencode --> rest_t : REST / x-api-key
mcp_t --> req_auth
sse_t --> req_auth
rest_t --> req_auth
rest_t --> meter : /api/connect/*
wh_t --> wh_router
req_auth --> dispatch
meter --> billing : resolve Customer
billing --> mysql : SELECT customers
billing --> redis : customer cache
dispatch --> c_wa
dispatch --> c_li
dispatch --> c_tg
dispatch --> c_dc
dispatch --> c_ig
dispatch --> c_tw
dispatch --> c_ob
c_wa --> cred_store : getCredential
c_li --> cred_store : getCredential
c_tg --> cred_store : getCredential
c_dc --> cred_store : getCredential
c_ig --> cred_store : getCredential
c_tw --> cred_store : getCredential
cred_store --> redis
wh_router --> redis
audit_log --> redis
c_wa --> meta_api
c_ig --> meta_api
c_li --> li_api
c_tg --> tg_api
c_dc --> dc_api
c_tw --> tw_api
c_ob --> ob_vault
oauth --> mysql
@enduml