Implement Phase 0b base project against the frozen test contract

All seven services (gateway, ledger, fraud, sanctions, insights, notifier,
audit), db/schema.sql plus optional_indexes.sql, scripts/seed.py and
smoke.py, the gateway-served frontend, and docker-compose.yml. Plain-text
stdlib logging and a weak manual X-Request-Id only -- no observability yet,
by design, per test_no_observability.py. Implements all 13 named chaos-flag
pathologies from docs/PATHOLOGIES.md behind Redis-backed runtime flags.

make smoke and make test-contract pass; make test-baseline and
make test-pathology pass except for a handful of load-sensitive tests
documented in tests/README.md rather than papered over.
This commit is contained in:
Movses Aslanyan
2026-09-05 08:12:30 +03:30
parent ccf1783779
commit 91afea92a1
51 changed files with 2757 additions and 0 deletions
+205
View File
@@ -0,0 +1,205 @@
x-app-env: &app-env
POSTGRES_DSN: postgresql+asyncpg://ledgerline:ledgerline@postgres:5432/ledgerline
REDIS_URL: redis://redis:6379/0
GATEWAY_URL: http://gateway:8000
LEDGER_URL: http://ledger:8001
FRAUD_URL: http://fraud:8002
SANCTIONS_URL: http://sanctions:8003
INSIGHTS_URL: http://insights:8004
NOTIFIER_URL: http://notifier:8005
x-app-build: &app-build
build:
context: .
dockerfile: Dockerfile
x-app-volumes: &app-volumes
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
x-app-depends: &app-depends
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
services:
postgres:
image: postgres:16-alpine
# max_connections=300: five separate services each keep their own
# SQLAlchemy pool (several sized up to pool_size=20+max_overflow=10),
# all against this one Postgres instance -- comfortably clears the
# default 100 under concurrent load instead of silently rationing
# connections in a way that looks like an unrelated pathology.
command:
- postgres
- -c
- shared_preload_libraries=pg_stat_statements
- -c
- pg_stat_statements.track=all
- -c
- pg_stat_statements.max=10000
- -c
- max_connections=300
environment:
POSTGRES_USER: ledgerline
POSTGRES_PASSWORD: ledgerline
POSTGRES_DB: ledgerline
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ledgerline -d ledgerline"]
interval: 3s
timeout: 3s
retries: 20
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 3s
timeout: 3s
retries: 20
gateway:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: gateway
command: uvicorn services.gateway.app:app --host 0.0.0.0 --port 8000 --reload --no-access-log
ports:
- "8000:8000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
ledger:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: ledger
command: uvicorn services.ledger.app:app --host 0.0.0.0 --port 8001 --reload --no-access-log
ports:
- "8001:8001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
fraud:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: fraud
command: uvicorn services.fraud.app:app --host 0.0.0.0 --port 8002 --reload --no-access-log
ports:
- "8002:8002"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8002/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
sanctions:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: sanctions
command: uvicorn services.sanctions.app:app --host 0.0.0.0 --port 8003 --reload --no-access-log
ports:
- "8003:8003"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8003/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
insights:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: insights
command: uvicorn services.insights.app:app --host 0.0.0.0 --port 8004 --reload --no-access-log
ports:
- "8004:8004"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8004/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
notifier:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: notifier
command: uvicorn services.notifier.app:app --host 0.0.0.0 --port 8005 --reload --no-access-log
ports:
- "8005:8005"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8005/healthz"]
interval: 5s
timeout: 3s
retries: 10
start_period: 10s
audit:
<<: [*app-build, *app-depends]
volumes:
- ./common:/app/common
- ./services:/app/services
- ./db:/app/db
- ./scripts:/app/scripts
environment:
<<: *app-env
SERVICE_NAME: audit
command: python -m services.audit.worker
volumes:
pgdata: