3f8bc58ca9
Phase 1 — Core API (Go): - Events, guests, tokens, RSVPs CRUD on PostgreSQL via pgx/v5 - HMAC-signed per-guest tokens with format validation - Health endpoint with DB ping, slog JSON logging, graceful shutdown Phase 2 — NATS + Fraud Engine: - NATS JetStream pub/sub with explicit-ack consumers - Python/FastAPI fraud engine with heuristic risk scoring (fingerprint mismatch, IP change, missing signals, repeated access) - gRPC sync scoring with 250ms fail-open timeout - Per-guest baseline tracking; risk bands low/medium/high/block Phase 3 — Notifications + Frontend: - Notification worker scaffolding (Twilio/SES stubs, retry/backoff) - Nuxt 3 frontend with Tailwind dark theme + brand green - Live monitor via WebSocket with auto-reconnect - Activity history endpoint backfills monitor with RSVPs + scored access checks (including blocked attempts) UX polish: - Marketing-friendly landing page (hero mockup, how-it-works, features, use cases, testimonials, FAQ, final CTA) - Animated layered card mockups on landing + new-event page - Plus-ones stepper, RSVP status badges, filter buttons - Friendly access-check labels (Verified/Review/Suspicious/Blocked) - Dashboard hydration fix via ClientOnly wrapper Infrastructure: - docker-compose for full local dev (postgres, nats, api, fraud-engine, notifier, frontend) - Multi-stage Dockerfiles, non-root UID 1000 - Integration tests with testcontainers-go Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
107 lines
2.4 KiB
YAML
107 lines
2.4 KiB
YAML
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
environment:
|
|
POSTGRES_USER: guestguard
|
|
POSTGRES_PASSWORD: guestguard
|
|
POSTGRES_DB: guestguard
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- postgres-data:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U guestguard -d guestguard"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
nats:
|
|
image: nats:2.10-alpine
|
|
command:
|
|
- "-js"
|
|
- "-sd"
|
|
- "/data"
|
|
- "-m"
|
|
- "8222"
|
|
ports:
|
|
- "4222:4222"
|
|
- "8222:8222"
|
|
volumes:
|
|
- nats-data:/data
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-qO-", "http://localhost:8222/healthz"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 10
|
|
|
|
api:
|
|
build:
|
|
context: .
|
|
dockerfile: cmd/api/Dockerfile
|
|
environment:
|
|
GG_ENV: development
|
|
GG_HTTP_ADDR: :8080
|
|
GG_DATABASE_URL: postgres://guestguard:guestguard@postgres:5432/guestguard?sslmode=disable
|
|
GG_NATS_URL: nats://nats:4222
|
|
GG_FRAUD_GRPC_ADDR: fraud-engine:9091
|
|
GG_FRAUD_GRPC_TIMEOUT: 250ms
|
|
GG_TOKEN_SECRET: dev-only-insecure-secret-change-me
|
|
ports:
|
|
- "8080:8080"
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
nats:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
fraud-engine:
|
|
build:
|
|
context: ./fraud-engine
|
|
dockerfile: Dockerfile
|
|
environment:
|
|
GG_ENV: development
|
|
GG_HTTP_ADDR: 0.0.0.0:8081
|
|
GG_GRPC_ADDR: 0.0.0.0:9091
|
|
GG_NATS_URL: nats://nats:4222
|
|
ports:
|
|
- "8081:8081"
|
|
- "9091:9091"
|
|
depends_on:
|
|
nats:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
notifier:
|
|
build:
|
|
context: .
|
|
dockerfile: cmd/notifier/Dockerfile
|
|
environment:
|
|
GG_ENV: development
|
|
GG_DATABASE_URL: postgres://guestguard:guestguard@postgres:5432/guestguard?sslmode=disable
|
|
GG_NATS_URL: nats://nats:4222
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
nats:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile
|
|
environment:
|
|
NODE_ENV: production
|
|
NUXT_PUBLIC_API_BASE: http://localhost:8080
|
|
NUXT_PUBLIC_WS_BASE: ws://localhost:8080
|
|
ports:
|
|
- "3000:3000"
|
|
depends_on:
|
|
- api
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
postgres-data:
|
|
nats-data:
|