Services
Services
Section titled “Services”Sencai uses an event-driven microservices architecture, orchestrated via Docker Compose (orchestration/). Each service has a clear responsibility. This page is an index grouped the same way as the monorepo itself; detailed pages exist for a handful of the most complex services.
Core platform
Section titled “Core platform”sencai.space
Section titled “sencai.space”- Role: Backend CMS / primary API — 212 content-types
- Tech: Strapi v5, Node.js, TypeScript, MySQL
- Port: 1337 (admin at
1337/admin) - Docs: Strapi backend
sencai-backend
Section titled “sencai-backend”- Role: Go strangler-fig replacement for
sencai.space— content-type by content-type parity behind the same HTTP contract, so traffic can eventually move over one route at a time. Shadow-only: not wired into default orchestration profiles, routes no real customer traffic. Strapi remains the platform’s only live backend. - Tech: Go, own MySQL (
go-backend-db, split frombackend-db2026-07-06) - Port: 8080 internally, host
go-backend.sencai.localhost, profilego-backend(not inDEFAULT_PROFILES) - Docs: Go Backend Migration — Developer Reference
sencai.space-frontend
Section titled “sencai.space-frontend”- Role: Platform UI — auth flow and gravity dashboard (organisations, cloud instances)
- Tech: Nuxt 3, Vue 3, Vuetify 3, Pinia
- Port: 3000
sencai-web
Section titled “sencai-web”- Role: Public marketing site (
sencai.space) — static, 15 locales - Tech: Astro 5 SSG, vanilla CSS, Three.js hero, served by nginx
- Port: served on nginx port 80 inside the container, reached via Traefik host routing (
sencai.localhostlocally,sencai.spacein production) — not a raw dev port
sencai-audit
Section titled “sencai-audit”- Role: Audit trail viewer SPA — immutable event log per organisation
- Tech: Nuxt 3, Keycloak OIDC (client
sencai-audit) - Port: 3300 · Host:
audit.sencai.localhost - Docs: Audit Trail
sencai-admin
Section titled “sencai-admin”- Role: Internal admin dashboard — user and organisation management
- Tech: Nuxt 3, Vue 3, Keycloak OIDC
- Port: 3100
api-manager
Section titled “api-manager”- Role: API token management and encryption
- Tech: Fastify 5, TypeScript, AES-256-GCM
- Port: 3200
- Docs: API Manager
Auth / Git / Webhook integration
Section titled “Auth / Git / Webhook integration”auth-service
Section titled “auth-service”- Role: Keycloak configuration and custom themes (not a running app — config directory consumed by the
keycloakcontainer) - Tech: Keycloak realm config,
themes/ - Port: Keycloak itself listens on 8180 (behind
/kc) - Docs: Keycloak authentication
auth-service-consumer
Section titled “auth-service-consumer”- Role: RabbitMQ consumer — syncs Strapi user/org events into Keycloak, plus the audit-consumer process (hash-chained audit log persistence)
- Tech: Node.js
- RabbitMQ: consumes
userandorganisationexchanges;audit-consumer.jsconsumesaudit.events
webhook-publisher
Section titled “webhook-publisher”- Role: Bridges Strapi webhooks into RabbitMQ
- Tech: Koa (the one deliberate exception to the TypeScript convention — plain JavaScript)
- Port: 1347
- Docs: Webhook Publisher
git-connector
Section titled “git-connector”- Role: RabbitMQ consumer — syncs Gitea repositories/organisations
- Tech: Express, TypeScript
- Port: 3002
- RabbitMQ: consumes
git.events - Docs: Git Connector
git-service
Section titled “git-service”- Role: Gitea instance configuration — two separate instances: Toolbox (system repos/templates) and Apps (user applications)
- Tech: Config only (upstream Gitea image), shared MySQL on port 3308
- Ports: Toolbox HTTP 9023 / SSH 9022, Apps HTTP 9034 / SSH 9033
Cloud / Infra
Section titled “Cloud / Infra”cloud-connector
Section titled “cloud-connector”- Role: Multi-cloud provisioning — REST/SDK calls directly to provider APIs (AWS, GCP, Azure, Hetzner, DigitalOcean, Vultr, Linode), plus its worker process consuming
cloud.events - Tech: TypeScript, TypeORM, PostgreSQL
- Port: 4321
- Docs: Cloud Connector
infra-gcp
Section titled “infra-gcp”- Role: CDKTF (Terraform CDK) IaC for Sencai’s own production multi-region infrastructure on GCP — not a running service, a deploy-time tool
- Tech: TypeScript, CDKTF
- Port: n/a — not a compose service, deployed independently of
orchestration/
k8s-agent
Section titled “k8s-agent”- Role: Kubernetes fleet agent — Helm chart / manifests for managed K8s clusters
- Tech: Helm, Kubernetes manifests
- Port: n/a — not a compose service, deployed independently of
orchestration/
Fleet / Agent / Opsloop
Section titled “Fleet / Agent / Opsloop”agent-gateway
Section titled “agent-gateway”- Role: C2 (command-and-control) gateway for on-host fleet agents — WebSocket + REST
- Tech: Go
- Port: 4400
sencai-agent
Section titled “sencai-agent”- Role: On-host fleet agent binary — monitoring, patch management, software inventory, runbook execution
- Tech: Go, distributed as a standalone binary (deb/rpm packaging, systemd unit), not a Docker Compose service
- Port: n/a — communicates outbound to
agent-gateway
ssh-proxy-service
Section titled “ssh-proxy-service”- Role: Browser terminal — SSH/WebSocket proxy
- Tech: Node.js, TypeScript
- Port: 3400
opsloop-consumer
Section titled “opsloop-consumer”- Role: OPSLOOP intelligence loop — RCA (root cause analysis) and remediation suggestions
- Tech: Node.js, TypeScript
- Port: 3005
- RabbitMQ: consumes
alertmanager.events(routing keyalert.firing) - Docs: OPSLOOP
gamification-consumer
Section titled “gamification-consumer”- Role: Sole writer of the
user-rank/gamification-eventcontent-types (F4.GAM) — computes XP/rank/badge changes server-side from platform activity, never trusting the amount claimed by an inbound message - Tech: Node.js, TypeScript, Pino
- Port: 3800 (health check only)
- RabbitMQ: consumes
gamification.events(topic); re-publishesrank.up/badge.awarded/easter-egg.triggeredonto the same exchange for the frontend notification bridge - Docs: Gamification Consumer
forum-connector
Section titled “forum-connector”- Role: JIT (just-in-time) provisioning bridge between Keycloak and
sencai-forum(Lemmy) — auto-registers a Lemmy account on a user’s first forum visit, syncs the KCforum-adminrole to Lemmy admin, polls Lemmy for unread replies/mentions and forwards them tonotification-service, and auto-provisions a Lemmy community whenever a new organisation is created in Strapi - Tech: Fastify 5, TypeScript
- Port: 4181
- RabbitMQ: consumes
organisation.forum-community-requested; publishes tonotification.events - Docs: Community Forum — Developer Reference
Billing / LLM / Notification / Events
Section titled “Billing / LLM / Notification / Events”billing-adapter
Section titled “billing-adapter”- Role: Usage events → Lago (metering) and Stripe (payments) bridge
- Tech: Node.js, TypeScript
- Port: 3600
- Docs: Billing Adapter
sencai-watchdog
Section titled “sencai-watchdog”- Role: Dunning microservice — payment-failure suspend/archive cron
- Tech: Node.js, TypeScript
- Port: 3700
llm-service
Section titled “llm-service”- Role: LLM facade — multi-provider LLM access for the platform
- Tech: Node.js, TypeScript
- Port: 4430
notification-service
Section titled “notification-service”- Role: Email + Slack consumer for
notification.events - Tech: Node.js, TypeScript
event-store-consumer
Section titled “event-store-consumer”- Role: Consumes the
platform.eventsfanout and ingests events into Strapi - Tech: Node.js, TypeScript
workspace-connector
Section titled “workspace-connector”- Role: Google Workspace Directory API sync
- Tech: Node.js, TypeScript
- Port: 3500
graphql-gateway
Section titled “graphql-gateway”- Role: GraphQL facade — unified schema over Strapi’s REST APIs
- Tech: Fastify 5, TypeScript, Apollo Server 5
- Port: 4000
- Docs: GraphQL Gateway
Standalone / support
Section titled “Standalone / support”bootstrap
Section titled “bootstrap”- Role: One-shot database bootstrap/seed scripts for Strapi
- Tech: Node.js, TypeScript
sencai-mq
Section titled “sencai-mq”- Role: Standalone RabbitMQ broker, plus its own messaging consumers
- Tech: RabbitMQ (upstream image)
- Port: 5673 (AMQP), 15673 (management UI)
sencai-forum
Section titled “sencai-forum”- Role: Community forum
- Tech: Lemmy 0.19, oauth2-proxy sidecar for Keycloak SSO
- Port: Lemmy backend API 8536, oauth2-proxy 4180
- Docs: Community Forum — Developer Reference
backup-scheduler
Section titled “backup-scheduler”- Role: Daily MySQL backup to S3/GCS, plus restore drills
- Tech: Node.js, TypeScript
sencai-docs
Section titled “sencai-docs”- Role: This documentation site
- Tech: Astro 5, Starlight, nginx
sencai-e2e
Section titled “sencai-e2e”- Role: End-to-end test suite against the live orchestrated stack
- Tech: Playwright, TypeScript
Retired services
Section titled “Retired services”cloud-consumer and git-consumer (HTTP bridge consumers) have been removed (ADR-001). cloud-connector’s worker process now consumes cloud.events directly; git synchronisation is handled entirely by git-connector. Do not reference either retired service in new documentation.
RabbitMQ exchanges
Section titled “RabbitMQ exchanges”| Exchange | Type | Notes |
|---|---|---|
user | direct | Strapi user create/update → auth-service-consumer |
organisation | direct | Strapi organisation create/update |
cloud.events | topic | Cloud provisioning, consumed by cloud-connector worker |
git.events | topic | Gitea sync, consumed by git-connector |
notification.events | topic | Email/Slack dispatch, consumed by notification-service |
audit.events | topic | Routing key audit.write; consumed by the audit-consumer process |
platform.events | fanout | All platform events, consumed by event-store-consumer for Strapi ingest |
alertmanager.events | topic | Monitoring alerts, routing key alert.firing, consumed by opsloop-consumer |
gamification.events | topic | XP/rank/badge activity, consumed by gamification-consumer (routing keys xp.granted, badge.check, streak.tick, easter-egg.roll) |
Fallback queues have a 14-day TTL. Retry logic caps at 5 attempts with exponential backoff.
Databases
Section titled “Databases”| Service | Engine | Host | Dev port |
|---|---|---|---|
| Strapi backend | MySQL | backend-db | 3306 |
| Keycloak | MySQL | keycloak-db | 3307 |
| Gitea | MySQL | git-service-mysql | 3308 |
| Cloud Connector | PostgreSQL | cloud-connector-db | 5434 |
| Forum | PostgreSQL | forum-db | 5435 |
Ports summary
Section titled “Ports summary”| Service | Port |
|---|---|
| Traefik | 80, 8080 |
| Strapi | 1337 |
| sencai.space-frontend | 3000 |
| sencai-audit | 3300 |
| sencai-admin | 3100 |
| API Manager | 3200 |
| Git Connector | 3002 |
| workspace-connector | 3500 |
| billing-adapter | 3600 |
| sencai-watchdog | 3700 |
| ssh-proxy-service | 3400 |
| opsloop-consumer | 3005 |
| gamification-consumer | 3800 |
| forum-connector | 4181 |
| graphql-gateway | 4000 |
| Cloud Connector | 4321 |
| agent-gateway | 4400 |
| llm-service | 4430 |
| Webhook Publisher | 1347 |
| RabbitMQ (sencai-mq) | 5672 (AMQP), 15672 (UI) — standalone sencai-mq on 5673/15673 |
| Keycloak | 8180 (behind /kc) |
| HashiCorp Vault | 8200 |
| Grafana | 3000 (host grafana.sencai.localhost) |
| Gitea Toolbox | 9023 (HTTP), 9022 (SSH) |
| Gitea Apps | 9034 (HTTP), 9033 (SSH) |
Read the root CLAUDE.md for complete architectural details and data flows.