{"repo":"bitfent/cryptocuz","private":true,"description":null,"default_branch":"main","stars":0,"forks":0,"pushed_at":"2026-08-05T18:17:39Z","languages":{"Python":424690,"PLpgSQL":5088,"Shell":1875,"Dockerfile":571},"files":119,"tree":[".env.example",".gitignore",".python-version","BUILD_01_servizio_api_origin.md","BUILD_02_worker_pipeline.md","BUILD_03_collectors.md","BUILD_04_integrazione_deepseek.md","BUILD_05_notability_registry.md","BUILD_06_infrastruttura.md","BUILD_07_marketplace_pricing.md","DESIGN_crypto_8h_digest_tecnico.md","Dockerfile","PITCH_criptocuz_business.pdf","README.md","SPEC_crypto_8h_digest_api.md","TRACKER.md","agent/__init__.py","agent/assemble.py","agent/collect.py","agent/config.py","agent/dedupe.py","agent/models.py","agent/normalize.py","agent/notability.py","agent/orchestrator.py","agent/planner.py","agent/registry_consolidate.py","agent/registry_outcomes.py","agent/registry_scoring.py","agent/registry_sink.py","agent/resolver.py","agent/scoring.py","agent/select.py","agent/synthesizer.py","agent/synthetic_season.py","agent/verifier.py","app/__init__.py","app/auth.py","app/cache.py","app/deps.py","app/errors.py","app/main.py","app/observability.py","app/ratelimit.py","app/routes/__init__.py","app/routes/digest.py","app/routes/internal.py","app/scheduler.py","app/schemas.py","app/storage.py","collectors/__init__.py","collectors/base.py","collectors/coingecko.py","collectors/defillama.py","collectors/mock.py","collectors/news_rss.py","collectors/x_budget.py","collectors/x_social.py","config/llm_pricing.yaml","config/llm_profiles.yaml","config/registry_enrichment.yaml","config/scoring.yaml","config/sources.yaml","config/synthesis.yaml","config/x_pricing.yaml","db/migrations/001_init.sql","db/migrations/002_registry_scoring.sql","db/migrations/003_x_budget.sql","db/migrations/004_registry_overrides.sql","db/migrations/005_resolution_cache.sql","db/migrations/006_lockdown_data_api.sql","docker-compose.yml","docs/registry_A_aggiornamento_incrementale.md","docs/registry_B_seeding_iniziale.md","llm/__init__.py","llm/accounting.py","llm/calls.py","llm/client.py","llm/errors.py","llm/fake.py","llm/parsing.py","llm/profiles.py","out/smoke_x_fields.json","out/smoke_x_fields_controllo.json","pyproject.toml","registry/RUBRIC.md","registry/aliases.yaml","requirements.txt","scripts/ask.sh","scripts/export_openapi.py","scripts/migrate.py","scripts/registry_consolidate.py","scripts/registry_tool.py","scripts/smoke_x_fields.py","tests/conftest.py","tests/fixtures/digest_response.schema.json","tests/fixtures/digest_response_golden.json","tests/integration/__init__.py","tests/integration/conftest.py","tests/integration/test_pg_parity.py","tests/test_api_layer.py","tests/test_collectors.py","tests/test_config_hygiene.py","tests/test_eval_split.py","tests/test_llm.py","tests/test_notability_merge.py","tests/test_orchestrator_e2e.py","tests/test_pipeline_steps.py","tests/test_registry_consolidate.py","tests/test_registry_outcomes.py","tests/test_registry_scoring.py","tests/test_registry_storage.py","tests/test_registry_supervision.py","tests/test_resolver.py","tests/test_scheduler.py","tests/test_schema_contract.py","tests/test_synthetic_season.py","tests/test_verifier.py","tests/test_x_budget.py"],"sizes":{".env.example":2273,".gitignore":142,".python-version":5,"BUILD_01_servizio_api_origin.md":29682,"BUILD_02_worker_pipeline.md":32636,"BUILD_03_collectors.md":29593,"BUILD_04_integrazione_deepseek.md":27165,"BUILD_05_notability_registry.md":42277,"BUILD_06_infrastruttura.md":34410,"BUILD_07_marketplace_pricing.md":29312,"DESIGN_crypto_8h_digest_tecnico.md":35096,"Dockerfile":571,"PITCH_criptocuz_business.pdf":268787,"README.md":10145,"SPEC_crypto_8h_digest_api.md":46543,"TRACKER.md":17641,"agent/__init__.py":0,"agent/assemble.py":6942,"agent/collect.py":3698,"agent/config.py":1034,"agent/dedupe.py":2688,"agent/models.py":10621,"agent/normalize.py":1807,"agent/notability.py":13538,"agent/orchestrator.py":7628,"agent/planner.py":5472,"agent/registry_consolidate.py":13544,"agent/registry_outcomes.py":9022,"agent/registry_scoring.py":9333,"agent/registry_sink.py":2468,"agent/resolver.py":5014,"agent/scoring.py":6448,"agent/select.py":1769,"agent/synthesizer.py":7622,"agent/synthetic_season.py":7138,"agent/verifier.py":7326,"app/__init__.py":0,"app/auth.py":2356,"app/cache.py":1592,"app/deps.py":3269,"app/errors.py":913,"app/main.py":12847,"app/observability.py":2360,"app/ratelimit.py":669,"app/routes/__init__.py":0,"app/routes/digest.py":5185,"app/routes/internal.py":1457,"app/scheduler.py":8206,"app/schemas.py":5454,"app/storage.py":39555,"collectors/__init__.py":0,"collectors/base.py":5752,"collectors/coingecko.py":3647,"collectors/defillama.py":2247,"collectors/mock.py":6381,"collectors/news_rss.py":2670,"collectors/x_budget.py":4706,"collectors/x_social.py":7566,"config/llm_pricing.yaml":364,"config/llm_profiles.yaml":1892,"config/registry_enrichment.yaml":5285,"config/scoring.yaml":904,"config/sources.yaml":2380,"config/synthesis.yaml":744,"config/x_pricing.yaml":295,"db/migrations/001_init.sql":5088,"db/migrations/002_registry_scoring.sql":1628,"db/migrations/003_x_budget.sql":558,"db/migrations/004_registry_overrides.sql":855,"db/migrations/005_resolution_cache.sql":612,"db/migrations/006_lockdown_data_api.sql":2954,"docker-compose.yml":522,"docs/registry_A_aggiornamento_incrementale.md":10885,"docs/registry_B_seeding_iniziale.md":22621,"llm/__init__.py":0,"llm/accounting.py":1718,"llm/calls.py":2188,"llm/client.py":4959,"llm/errors.py":405,"llm/fake.py":3303,"llm/parsing.py":1095,"llm/profiles.py":1763,"out/smoke_x_fields.json":11463,"out/smoke_x_fields_controllo.json":3602,"pyproject.toml":1088,"registry/RUBRIC.md":7257,"registry/aliases.yaml":761,"requirements.txt":1326,"scripts/ask.sh":1875,"scripts/export_openapi.py":497,"scripts/migrate.py":1341,"scripts/registry_consolidate.py":2836,"scripts/registry_tool.py":5894,"scripts/smoke_x_fields.py":14927,"tests/conftest.py":2638,"tests/fixtures/digest_response.schema.json":15191,"tests/fixtures/digest_response_golden.json":3471,"tests/integration/__init__.py":0,"tests/integration/conftest.py":3849,"tests/integration/test_pg_parity.py":10267,"tests/test_api_layer.py":12470,"tests/test_collectors.py":12284,"tests/test_config_hygiene.py":2199,"tests/test_eval_split.py":3737,"tests/test_llm.py":7333,"tests/test_notability_merge.py":5528,"tests/test_orchestrator_e2e.py":7389,"tests/test_pipeline_steps.py":11844,"tests/test_registry_consolidate.py":8387,"tests/test_registry_outcomes.py":4508,"tests/test_registry_scoring.py":10855,"tests/test_registry_storage.py":3672,"tests/test_registry_supervision.py":5274,"tests/test_resolver.py":3099,"tests/test_scheduler.py":6291,"tests/test_schema_contract.py":2393,"tests/test_synthetic_season.py":2191,"tests/test_verifier.py":6531,"tests/test_x_budget.py":11081},"readme":"# CryptoCuz — 8h crypto digest API\n\n**Stato: pre-alpha 0.0.0.1** — prima implementazione della SPEC (`SPEC_crypto_8h_digest_api.md`)\ne dei piani BUILD_01–07. Un endpoint a chiamata singola che, dato un argomento crypto,\nrestituisce un briefing delle ultime 8 ore: cosa è successo, chi lo sta dicendo, quanto conta,\ncon fonti e livello di confidenza.\n\n## Avvio in locale\n\n```bash\nuv venv --python 3.12 .venv\nuv pip install -e '.[dev]'\ncp .env.example .env          # compilare le chiavi che si hanno\n.venv/bin/uvicorn app.main:app --port 8000\n```\n\nSenza alcuna chiave il servizio parte comunque (V10): `x_social` disabilitato e dichiarato,\nstore in-memory (solo dev), e la sintesi risponde `503` onesto finché manca `DEEPSEEK_API_KEY`.\n\n```bash\ncurl -s localhost:8000/health\ncurl -s -X POST localhost:8000/v1/digest -H 'Content-Type: application/json' \\\n     -d '{\"topic\":\"hyperliquid\",\"depth\":\"standard\"}'\n```\n\nTest e lint:\n\n```bash\n.venv/bin/python -m pytest        # 239 test, offline, niente rete (i @live sono esclusi)\n.venv/bin/ruff check .\n```\n\n## Deploy su Render (web service nativo, senza Docker e senza blueprint)\n\nIl servizio si deploya come **Web Service** con runtime Python, configurato a mano\nin dashboard. Niente `render.yaml`: il deploy resta un gesto esplicito.\n\n| Campo | Valore |\n| --- | --- |\n| Runtime | Python 3 |\n| Build command | `pip install -r requirements.txt` |\n| Start command | `uvicorn app.main:app --host 0.0.0.0 --port $PORT` |\n| Health check path | `/health` |\n\nDue file nel repo servono al deploy e a nient'altro:\n\n- `.python-version` (**3.12**) — Render dal 11/02/2026 crea i servizi con Python\n  **3.14**; lo stack è validato su 3.12 e il pin evita che l'interprete cambi\n  sotto i piedi al primo deploy. Alzarlo è una modifica deliberata, con suite verde.\n- `requirements.txt` — lock delle versioni esatte con cui la suite gira verde.\n  `pyproject.toml` resta la fonte dei *range* ammessi; qui c'è la combinazione\n  effettivamente provata. Il pacchetto non serve installarlo: `uvicorn` mette la\n  working dir in testa a `sys.path`, quindi `app/`, `config/` e `registry/`\n  si risolvono dal checkout.\n\nVariabili d'ambiente (i segreti si compilano in dashboard, mai nel repo):\n\n```\nENV=prod\nRELAY_SHARED_SECRET=<segreto condiviso col relay>   # oppure API_KEYS\nSUPABASE_DB_URL=<connection string del pooler, porta 6543>\nDEEPSEEK_API_KEY=<chiave>\nSYNTH_MODEL=deepseek-v4-flash\nX_BEARER_TOKEN=<opzionale: vuoto = collector X spento e costo social azzerato>\nX_DAILY_CAP_USD=<soffitto giornaliero, default 15>\nSCHEDULER_ENABLED=false\n```\n\nTre cose che valgono la pena sapere prima di accendere:\n\n1. **`ENV=prod` è fail-closed, e va tenuto così.** Senza `RELAY_SHARED_SECRET`\n   (o `API_KEYS`) il servizio *si rifiuta di partire* (`app/auth.py`), e lo stesso\n   senza `SUPABASE_DB_URL` (`app/storage.py`). Non aggirare l'errore mettendo\n   `ENV=dev`: in quel caso l'`open_mode` autentica chiunque, e ogni chiamata\n   all'endpoint costa lettura X reale.\n2. **`SCHEDULER_ENABLED=false` finché l'advisory lock non è sistemato.**\n   `PostgresStorage.run_lock` assume che `pg_try_advisory_lock` sia di sessione,\n   ma il pooler Supabase in transaction mode (6543) multiplexa più connessioni\n   sullo stesso backend: due chiamanti ottengono entrambi il lock (è rientrante) e\n   l'unlock singolo lascia il refcount a 1. L'esclusione «una sola esecuzione per\n   orario» **non** vale (vedi BUILD_06 P4/D-INF-7, da rifare come lease su tabella).\n3. **La connection string deve essere quella del pooler (6543).** L'host diretto\n   `db.<ref>.supabase.co:5432` è solo IPv6 e da Render non si risolve.\n   `statement_cache_size=0` è già gestito nel codice (D-INF-2).\n\nLe migration si applicano **prima** del primo avvio, da locale, puntando allo\nstesso DB: `python scripts/migrate.py` (idempotente).\n\n## Architettura (SPEC §4)\n\n```\nPOST /v1/digest → API layer (auth X-Relay-Key · rate limit · cache 300s)\n               → Orchestrator: plan → collect → normalize → dedupe → score\n   ","price_usd":"0.10","clone_checkout":"https://api.checkout402.com/c/chk_n0cayAj8e1uc9OSJ","rehearse_checkout":"https://api.checkout402.com/c/chk_n0cayAj8e1uc9OSJ/test","preview":"/r/bitfent/cryptocuz/f/<path> serves file CONTENTS for the seller's preview paths; other paths answer with the price","how_to_buy":"pay clone_checkout with x402 (pay402 does it in one call); the goods arrive as payload_base64, a tar.gz of the full repo. Rehearse first at rehearse_checkout: same flow, simulated money.","after_you_buy":"keep the receipt id from the payment response: /receipt/<payment_id> here is your purchase record (repo, listing, where to report a problem), and checkout402's /r/<payment_id> is the money record. Tell your human both URLs."}