Lo script deploy-noclone.sh ora carica automaticamente come ultimo -f
un eventuale $DEPLOY_DIR/docker-compose.local.yml se esiste. Utile per
fix specifici macchina (es. DOCKER_API_VERSION watchtower su daemon
vecchi). Gitignored per design — non versionato nel repo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skip login se ~/.docker/config.json contiene già auth per il registry.
Permette di fare 'docker login' una volta e poi lanciare lo script
senza dover esportare GITEA_PAT ad ogni run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per VPS condiviso (es. con Gitea) dove Traefik gestisce già 80/443.
- gateway/Caddyfile: env-aware listen + auto_https + trusted_proxies
(defaults invariati per modalità standalone).
- docker-compose.traefik.yml: overlay che rimuove ports binding host,
attacca gateway alla network esterna di Traefik, set labels per
routing Host(cerbero-mcp.tielogic.xyz) + TLS via certresolver
Traefik. Caddy ascolta plain HTTP :80 interno.
- scripts/deploy.sh: rileva BEHIND_TRAEFIK=true → aggiunge -f
docker-compose.traefik.yml a tutti i docker compose call.
- DEPLOYMENT.md: nuova sezione 2a (topologia standalone vs behind-traefik)
+ sotto-sezione modalità behind-Traefik con env vars richieste.
Uso:
docker compose -f docker-compose.prod.yml -f docker-compose.traefik.yml \
--env-file .env up -d
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README aggiunge sezione 'CI/CD pipeline' che descrive i 5 job e i tag
image. DEPLOYMENT espande sez. 1 con dettagli runner Gitea (network
gitea_gitea-internal, image runner-images, label ubuntu-latest) e
configurazione secret user-level REGISTRY_TOKEN con scope write:package.
Buildx con driver docker-container non vede image caricate nel daemon
locale. Soluzione: push base come git.tielogic.xyz/adriano/cerbero-mcp/
base:latest e i 6 service Dockerfile usano ${BASE_IMAGE}:${BASE_TAG}
con default "cerbero-base" per dev locale, override CI a path registry.
GITEA_TOKEN auto-iniettato non include write:package scope necessario per
push al registry. Serve PAT manuale creato in User Settings → Applications
con scope write:package, salvato come secret repo REGISTRY_TOKEN.
- 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>