feat: microservices scaffold + Auth Service (Step 1)

- Add shared/ module: config, db, models, schemas, redis utilities
- Add Auth Service (services/auth/): register, login, refresh, me,
  ForwardAuth /verify endpoint for Traefik
- Add Traefik config: ACME/Cloudflare DNS-01, dynamic routing,
  ForwardAuth middleware, sticky sessions for WS Gateway
- Add service scaffolds: ws-gateway, chat, batch-agent, billing (READMEs)
- Add redis>=5.0.0 to requirements.txt
- Monolith app/ is untouched — strangler fig migration
This commit is contained in:
Roberto Musso
2026-03-22 00:29:51 +01:00
parent 552b8eb305
commit aa219a4d08
25 changed files with 1685 additions and 0 deletions

143
traefik/dynamic/routers.yml Normal file
View File

@@ -0,0 +1,143 @@
# Dynamic routing configuration
http:
middlewares:
# ForwardAuth: validates JWT via Auth Service, injects identity headers
auth-forward:
forwardAuth:
address: "http://auth:8000/api/v1/auth/verify"
trustForwardHeader: true
authResponseHeaders:
- "X-User-Id"
- "X-User-Email"
- "X-User-Tier"
# Rate limiting (basic — per-client IP; upgrade to per-tier later)
rate-limit:
rateLimit:
average: 60
burst: 20
period: "1m"
# Strip /api/v1 prefix before forwarding to services
strip-api-prefix:
stripPrefix:
prefixes:
- "/api/v1"
routers:
# ── Auth (no ForwardAuth on public endpoints) ──────────────
auth-public:
rule: "PathPrefix(`/api/v1/auth/register`) || PathPrefix(`/api/v1/auth/login`) || PathPrefix(`/api/v1/auth/refresh`)"
entryPoints:
- websecure
middlewares:
- rate-limit
- strip-api-prefix
service: auth-svc
tls: {}
auth-protected:
rule: "PathPrefix(`/api/v1/auth`)"
entryPoints:
- websecure
middlewares:
- auth-forward
- rate-limit
- strip-api-prefix
service: auth-svc
tls: {}
# ── WebSocket Gateway (sticky sessions) ────────────────────
ws-gateway:
rule: "PathPrefix(`/api/v1/ws`)"
entryPoints:
- websecure
middlewares:
- rate-limit
service: ws-gateway-svc
tls: {}
# ── Chat Service ───────────────────────────────────────────
chat:
rule: "PathPrefix(`/api/v1/chat`)"
entryPoints:
- websecure
middlewares:
- auth-forward
- rate-limit
- strip-api-prefix
service: chat-svc
tls: {}
# ── Batch Agent Service ────────────────────────────────────
batch-agent:
rule: "PathPrefix(`/api/v1/agents`)"
entryPoints:
- websecure
middlewares:
- auth-forward
- rate-limit
- strip-api-prefix
service: batch-agent-svc
tls: {}
# ── Billing Service ────────────────────────────────────────
billing-webhook:
rule: "PathPrefix(`/api/v1/billing/webhook`)"
entryPoints:
- websecure
middlewares:
- rate-limit
- strip-api-prefix
service: billing-svc
tls: {}
priority: 10
billing:
rule: "PathPrefix(`/api/v1/billing`)"
entryPoints:
- websecure
middlewares:
- auth-forward
- rate-limit
- strip-api-prefix
service: billing-svc
tls: {}
# ── Health (no auth) ───────────────────────────────────────
health:
rule: "Path(`/api/v1/health`)"
entryPoints:
- websecure
service: auth-svc
tls: {}
services:
auth-svc:
loadBalancer:
servers:
- url: "http://auth:8000"
ws-gateway-svc:
loadBalancer:
sticky:
cookie:
name: "ws_affinity"
servers:
- url: "http://ws-gateway:8000"
chat-svc:
loadBalancer:
servers:
- url: "http://chat:8000"
batch-agent-svc:
loadBalancer:
servers:
- url: "http://batch-agent:8000"
billing-svc:
loadBalancer:
servers:
- url: "http://billing:8000"

39
traefik/traefik.yml Normal file
View File

@@ -0,0 +1,39 @@
# Traefik static configuration for microservices gateway
api:
dashboard: true
insecure: true # Dashboard on :8080 (internal only in prod)
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
http:
tls:
certResolver: cloudflare
providers:
docker:
exposedByDefault: false
file:
directory: /etc/traefik/dynamic
watch: true
# Automatic TLS via Let's Encrypt + Cloudflare DNS-01 challenge
certificatesResolvers:
cloudflare:
acme:
email: "${ACME_EMAIL}"
storage: /etc/traefik/acme/acme.json
dnsChallenge:
provider: cloudflare
delayBeforeCheck: 10
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"