Component documentation
This folder is the first place to read when learning the codebase. Each file describes one logical unit (a service, a plugin, a module), what it owns, what it depends on, and the security invariants it enforces.
Index
Phase 1 — Foundation
| Component | Source | Purpose |
|---|---|---|
| Database | src/db/ | Drizzle schema, RLS policies, role separation, TIMESTAMP parser override |
| Secrets loader | src/security/secrets.loader.ts | Loads sensitive material from systemd-creds (prod) or secrets/ (dev) |
| API key service | src/security/api-key.service.ts | Generates, hashes (HMAC-SHA256), and constant-time verifies API keys |
| Tenant middleware | src/security/tenant.middleware.ts | Resolves the tenant from X-Api-Key on /mcp/* and /auth/*/start |
| Rate limiter | src/security/rate-limiter.plugin.ts | Per-IP + per-tenant + per-route rate limits |
| IP block | src/security/ip-block.service.ts | Tracks auth-failure bursts, blocks offending IPs |
| Audit log | src/security/audit-log.service.ts | Append-only security event trail |
| Log scrubber | src/security/log-scrubber.ts | Redacts token-shaped strings from logs |
| OAuth state | src/auth/oauth-state.service.ts | PKCE + state parameter storage and cleanup |
| Admin routes | src/auth/admin-routes.ts | API key rotation endpoint |
| MCP server | src/mcp/server.ts | Tool registry + Streamable HTTP transport |
| MCP tools | src/mcp/tools/ | Phase 1 stub tools: ping, get_account_health |
| Entry point | src/index.ts | Bootstrap order, plugin registration, listener |
Phase 2 — Google Ads adapter
| Component | Source | Purpose |
|---|---|---|
| Cache service | src/cache/ | TTL cache + thundering-herd advisory lock + per-platform hit/miss metrics (PR-1) |
| Credentials service | src/security/credentials.service.ts | Per-tenant DEKs wrapped under the process KEK; envelope encryption for OAuth tokens (PR-2) |
| OAuth routes | src/auth/oauth-routes.ts | /auth/:platform/start + /callback (PR-4) |
| Google adapter | src/adapters/google/ + registry.ts | OAuth code exchange + token refresh (PR-4); GAQL queries (PR-5); revoke (PR-7) |
How the request flows
HTTP → helmet (headers)
→ @fastify/rate-limit (Layer 1: per-IP)
→ tenantAuthPlugin (X-Api-Key → req.tenantId, audit row;
covers /mcp/* AND /auth/*/start)
→ tenantLimiter (Layer 2: per-tenant)
→ adminRoutes / oauthRoutes / mountMcp / /health
├── /auth/google/start → 302 to Google (PKCE)
├── /auth/google/callback → adapter.exchangeAuthCode (no auth)
├── adminRoutes → /admin/api-keys/rotate
└── mountMcp delegates to McpServer
└── tool handler (audit row + business logic;
cache + adapters in Phase 2)Reading order recommended for new contributors:
entry-point.md— see how everything is wired.database.md— understand RLS + role separation, the heart of multi-tenancy.secrets-loader.md— understand why nothing reads fromprocess.env.tenant-middleware.md→audit-log.md→api-key-service.md— the auth chain end-to-end.mcp-server.md→mcp-tools.md— how tools plug into the registry.- Phase 2 reading order:
cache-service.md→credentials-service.md→oauth-routes.md→google-adapter.md.