- Nuovo job validate-config: docker compose -f docker-compose.{yml,prod.yml}
config -q (verifica sintassi YAML + variabili env) + caddy validate
--config Caddyfile (sintassi gateway).
- build-and-push ora needs anche validate-config: niente push image se
compose o Caddyfile sono rotti.
- Cache Docker buildx passata da type=gha (richiede backend cache server
Gitea Actions configurato) a type=registry,ref=<prefix>/buildcache:<name>
che usa il registry stesso come storage cache. Funziona out-of-the-box,
niente setup extra.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CI pipeline (.gitea/workflows/ci.yml):
- Job lint (ruff), typecheck (mypy mcp_common gating + servizi
warn-only), test (pytest 455).
- Job build-and-push solo su main: builda gateway + 6 image MCP via
docker/build-push-action@v6, login al registry Gitea con
docker/login-action@v3 + secrets.GITEA_TOKEN auto-iniettato.
- Cache distribuita type=gha per layer Docker → run successivi 5-10x
più veloci. Tag :latest + :sha-XXXXXXX per ogni image.
Deploy VPS (docker-compose.prod.yml):
- Niente build locale: solo `image:` da git.tielogic.xyz/adriano/
cerbero-mcp/<service>:latest. Variabile IMAGE_TAG per pin a sha
specifico.
- Servizio Watchtower containerizzato che polla ogni 5min (configurabile
via WATCHTOWER_POLL_INTERVAL) e auto-aggiorna i container con label
com.centurylinklabs.watchtower.enable=true. Auth registry riusa
~/.docker/config.json bind-mounted readonly.
DEPLOYMENT.md: runbook completo per setup VPS, login registry, secrets,
.env, smoke test post-deploy, rollback (pin a sha), disable auto-update,
nota Traefik upload limit. README aggiornato con link.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- mcp_common/http.py: nuovo helper async_client() con
AsyncHTTPTransport(retries=3) per gestire connection error transient
+ call_with_retry() generic async retry decorator. Sostituite 25
occorrenze httpx.AsyncClient(...) in deribit/hyperliquid/sentiment/
macro client. 5 nuovi test.
- Dockerfile healthcheck: passato da python+httpx subprocess a
stdlib urllib.request.urlopen() su tutti i 6 servizi MCP. Zero
dipendenze esterne nel runtime check, timeout esplicito 3s, image
leggermente più snella.
- pyproject.toml: aggiunto [tool.mypy] python_version=3.13 con
mypy_path multi-package + override ignore_missing_imports per i
vendor SDK (pybit, alpaca, hyperliquid, pythonjsonlogger). mypy 1.20
in dev deps; ruff pinned 0.5.x. mcp_common passa mypy clean; 44
errori tipo pre-esistenti nei servizi affiorati ma non bloccanti —
fix da pianificare separatamente.
- 455 test verdi.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- pyproject.toml: ruff target-version py311 → py313 (auto-fix 42 lint
warnings via UP rules); aggiunto consider_namespace_packages = true
che risolve la collisione conftest tra servizi e permette di lanciare
pytest sull'intera suite cross-servizio.
- mcp_common.audit: nuovo helper audit_write_op() con logger dedicato
mcp.audit. Wirato su tutti i write endpoint di deribit, bybit, alpaca
e hyperliquid (place_order, place_combo_order, cancel_*, set_*,
close_*, transfer_*, switch_*, amend_*) con principal + target +
payload non-sensibile + result summarizzato.
- mcp_common.app_factory: ExchangeAppSpec + run_exchange_main()
centralizza il boilerplate dei __main__.py (configure_root_logging,
fail_fast_if_missing, summarize, load creds, resolve_environment,
load token store, uvicorn). I 4 __main__.py exchange ridotti da ~60
LOC ognuno a ~25 LOC dichiarativi. mcp_common.env_validation
promosso da mcp_deribit (mantenuto re-export shim per back-compat
test_env_validation).
- 8 test nuovi (4 audit + 4 app_factory). Suite full: 450/450 verdi.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Configura il gateway Caddy per il deploy su cerbero-mcp.tielogic.xyz:
- Build custom Caddy con plugin mholt/caddy-ratelimit (Dockerfile +
build via xcaddy).
- TLS automatico via Let's Encrypt (richiede DNS A record + porte
80/443 raggiungibili), HSTS preload, header di sicurezza.
- Rate limit per IP (60 req/min sui read, 10 req/min sui write,
sliding window).
- Allowlist IP sui write endpoint (place_*, cancel_*, set_*, close_*,
transfer_*, amend_*, switch_*): IP non in WRITE_ALLOWLIST → 403.
- Default WRITE_ALLOWLIST copre loopback + Docker bridge: bot sulla
stessa macchina (host o container) funziona senza configurazione,
IP pubblici esterni vanno aggiunti esplicitamente.
- Smoke test e README aggiornati per il nuovo URL gateway.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deribit: private/create_combo + place_order sul combo instrument → una
sola crociata di spread invece di N (slippage atteso ridotto su
strutture liquide). ACL core + leverage cap su tutti i leg.
Bybit: place_batch_order su category=option (atomic multi-leg, 1
round-trip API). Reject su category != option (perp/linear non
supportano batch nativo). orderLinkId auto-generato per leg.
Tutti i test: deribit 48/48, bybit 123/123.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documentata la precedenza di risoluzione environment e l'utilizzo dei
nuovi kwargs default_base_url_live/testnet di resolve_environment.
Smoke README estesa con i 6 live tool check read-only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aggiunti kwargs opzionali default_base_url_live / default_base_url_testnet
a resolve_environment. Rimosse 8 chiamate creds.setdefault duplicate dai
4 servizi (alpaca, bybit, deribit, hyperliquid) ora passano gli URL
canonici direttamente al resolver.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>