System overview
One request path, one public entry point: the browser talks only to Traefik, and everything else — backend, MCP server, ai-service, Postgres — runs behind it on the private workload network.
Services
frontend-frontoffice— React + Vite SPA. Talks to the gateway only, never to the backend or ai-service directly.- Traefik — the single public origin (
:8443). Routes normal/api/*traffic to the backend and guards/api/ai/*with ForwardAuth. - Backend (
MyLegalTeam.Api, .NET 10, Clean Architecture) — one running instance,:8080. Owns the session, the domain, and Postgres. - MCP Server — runs in the same backend instance and process, not a separate deployable. It is
reached on a different path (
:8080/mcp) exposing tools and resources over the legal domain, consumed directly by ai-service as an MCP client. - ai-service (FastAPI) — AI drafting with SSE streaming (
:8010). - Postgres — sessions, application data, and the ASP.NET Data Protection keyring.
- Mailpit — local outbound email capture (
:8025). @mylegalteam/design-system— shared React component library, consumed at build time by the SPA and by Storybook (:6006); the Docusaurus docs (:3002) are a standalone site with no runtime dependency on any of this.
The AI gateway authorization mechanism
The browser never talks to ai-service directly. Traefik intercepts /api/ai/*, calls the backend's
ForwardAuth endpoint to validate the existing HttpOnly session, and gets back a short-lived RS256 JWT
(scope=ai:draft, 120-second TTL). Traefik strips the cookie and the gateway shared secret before
forwarding only that bearer token — there is no second browser session, no exchange endpoint, and no
Redis. ai-service validates the signature against the backend's JWKS, cached for 5 minutes.
See docs/superpowers/specs/2026-09-01-ai-gateway-auth.md
for the full design, threat model and production rotation procedure.
MCP runs in the backend, not beside it
The MCP server is part of the .NET 10 backend solution — same process, same port, same
deployment unit as the rest of the API. It is not a separate service with its own lifecycle, scaling,
or network boundary; it simply exposes a second path (/mcp) off the same instance. ai-service
consumes it directly as an MCP client for domain tools and resources, alongside the JWKS fetch it
already does to validate gateway tokens.
Local endpoints (tilt up)
| Service | Endpoint |
|---|---|
| Frontend | https://localhost:3000 |
| Gateway (Traefik) | https://localhost:8443 |
| Backend (debug/swagger) | https://localhost:8080/swagger |
| ai-service (debug) | https://localhost:8010/api/health |
| Traefik dashboard (dev) | http://localhost:8081/dashboard/ |
| Mailpit | http://localhost:8025 |
| Storybook | http://localhost:6006 |
| Docs | http://localhost:3002 |
See the root README.md for the full
first-run setup.