Files
dd0c/products/04-lightweight-idp/architecture/dual-mode-addendum.md
Max Mayfield c3bafa238a Add dual-mode deployment addendums for all 6 products
P1 route: 16 pts (template, full docker-compose + install script)
P2 drift: 17 pts (pgmq, local CA for mTLS)
P3 alert: 19 pts (Lambda→Fastify, DynamoDB→PG JSONB)
P4 portal: 18 pts (Step Functions→cron, Aurora→PG+pgvector)
P5 cost: 19 pts (EventBridge→agent/polling, DynamoDB→PG JSONB)
P6 run: 15 pts (easiest — already PG-native, no AWS deps in core)

Total self-hosted effort: ~104 story points across all 6 products
2026-03-01 02:00:00 +00:00

2.4 KiB

dd0c/portal — Dual-Mode Deployment Addendum

Template: Based on dd0c/route dual-mode pattern


Cloud → Self-Hosted Service Mapping

Cloud Service Self-Hosted Replacement Notes
Aurora Serverless v2 PostgreSQL container Same schema, pgvector extension
Step Functions Temporal or simple cron Discovery orchestration
Lambda (scanners) Scanner containers Same code, containerized
Cognito Local JWT (HS256) AuthProvider pattern
Meilisearch (managed) Meilisearch container Already self-hostable
S3 Local FS or MinIO Discovery artifacts
SES SMTP relay Notifications
CloudWatch Prometheus + Grafana Bundled

Self-Hosted Compose Services

services:
  api:              # Dashboard API + discovery orchestrator
    image: ghcr.io/dd0c/portal-api:latest
  scanner-aws:      # AWS discovery scanner
    image: ghcr.io/dd0c/portal-scanner-aws:latest
  scanner-github:   # GitHub discovery scanner
    image: ghcr.io/dd0c/portal-scanner-github:latest
  dashboard:        # React SPA with Cmd+K search
    image: ghcr.io/dd0c/portal-dashboard:latest
  postgres:         # Catalog + pgvector
    image: pgvector/pgvector:pg16
  meilisearch:      # Full-text search
    image: getmeili/meilisearch:latest
    volumes:
      - meili_data:/meili_data
  redis:            # Prefix cache for Cmd+K
    image: redis:7-alpine
  caddy:
    image: caddy:2-alpine

Key Difference: Step Functions → Cron

Self-hosted replaces Step Functions with a simple cron scheduler inside the API container:

  • AWS scan: every 6 hours
  • GitHub scan: every 4 hours
  • Scans run as background tasks, progress streamed via WebSocket (same as cloud)

Epic Impact

Epic Change Effort
1 (AWS Scanner) Lambda → container, Step Functions → cron 3 pts
2 (GitHub Scanner) Lambda → container 2 pts
3 (Service Catalog) Aurora → PostgreSQL container (same schema) 1 pt
4 (Search) Already Meilisearch — no change 0
5 (Dashboard UI) Local login form 2 pts
6 (Analytics) No change 0
7 (Dashboard API) LocalAuthProvider 2 pts
8 (Infrastructure) docker-compose.yml + install.sh 5 pts
9 (Onboarding) Local signup, remove Stripe req, WebSocket same 3 pts
10 (TF Tenets) No change 0
Total 18 pts