Releases: UPinar/contrastapi
v1.34.2 — resilient crypto payment provisioning + dependency/security bumps
Crypto billing — resilient payment provisioning
Crypto Pro payments are now provisioned automatically when the received
amount is within a small tolerance of the invoice (covering exchange and
network rounding), instead of requiring an exact-amount settlement.
Genuine underpayments and failed/expired/refunded payments are left
unprovisioned and surfaced to operators. Amounts are validated from the
signature-verified provider notification.
Operational visibility
Operator notifications added for underpaid / failed / expired / refunded
payments and for successful key claims.
Dependencies / security
- cryptography 48.0.0 → 48.0.1 (GHSA-537c-gmf6-5ccf)
- beautifulsoup4 → >=4.15.0
Tests
2579 passing. Wire-compatible — no API contract, MCP tool (54),
Resource (7) or Prompt (3) changes.
v1.34.0 — Free first call to every tool for new agents
What's new
New MCP agents commonly probe every tool once to discover what's available — that initial sweep could previously hit the hourly limit partway through. Now the first call to each distinct tool is free for keyless (Free-tier) callers: a one-time grant per caller, so an agent can complete its discovery pass without being rate-limited. Later calls fall back to the normal hourly limit.
Scope
- MCP
tools/callonly — REST endpoints and API-key (Pro) callers are unchanged. - Single-credit tools only; composite/orchestration tools keep their cost.
- One-time per caller.
Notes
- No contract changes — MCP tools (53), Resources (7), Prompts (3) and all schemas unchanged; existing integrations unaffected.
- Schema: an internal ledger table created idempotently on startup — no migration step, no downtime.
- Privacy/abuse: caller identity is hashed and bucketed; abuse-resistant by design.
- Tests: full suite green with added first-swipe coverage (2510 passing).
- Rollback: feature is flag-gated.
v1.33.24 — Recon pool hardening + dependency bumps
v1.33.24
Reliability
- recon: reap idle keepalive connections in the SSRF-safe HTTP pool — prevents idle-connection accumulation in the recon / domain-intelligence fetch path.
Dependencies
- uvicorn 0.48.0 → 0.49.0
- python-multipart 0.0.30 → 0.0.32
- phonenumbers 9.0.31 → 9.0.32
Unchanged
- 53 MCP tools · 7 Resources · 3 Prompts
- Full test suite green
Follows v1.33.23.
v1.33.22 — Optional outputSchema fields accept null (#42)
Fix: lean MCP outputSchema now accepts null for optional fields (#42)
Optional response fields (T | None) were advertised in the lean tools/list
outputSchema by their non-null type only — e.g. verdict as {"type": "object"}.
A tool returning null for such a field (where it isn't computed pre-enrichment)
then failed strict MCP client validation: -32602 ... must be object.
Fix: the null arm is preserved as a flat 2-element type array —
verdict: {"type": ["object", "null"]}, and likewise ["string","null"] /
["array","null"] / ["integer","null"] … for every other optional field.
Resolved centrally in the schema-derivation helper, so it applies to all 53
tools (223 nullable fields), not just verdict.
- Stays flat — no
$defs/$ref/anyOf— so strict clients (the lean-schema
consumers) keep validating cleanly. - Ambiguous / mixed-type unions stay permissive (
{}). - Verified on a Draft 2020-12 validator: a
nullverdict now validates; a
populated object verdict still does.
Wire-compatible bug fix; no tool/arg changes. MCP surface unchanged
(53 tools · 7 Resources · 3 Prompts). Test suite green.
Reported by @0xawad — thanks for the precise repro.
v1.33.21 — security: urllib3 + click CVE patches
Security
Patches three CVEs in transitive dependencies by pinning the fixed upstream versions. No application behavior change — both packages are transitive-only with no direct imports in app code.
- urllib3 2.6.3 → 2.7.0
- CVE-2026-44432 (HIGH): response could be fully decompressed instead of the requested portion on a second
read(amt=N)/ drain (Brotli). - CVE-2026-44431 (MED): sensitive headers forwarded on cross-origin redirects via the low-level
ProxyManagerpath.
- CVE-2026-44432 (HIGH): response could be fully decompressed instead of the requested portion on a second
- click 8.3.1 → 8.3.3
- CVE-2026-7246 (HIGH): command injection in
click.edit(). Not reachable from the server (click is transitive via uvicorn/typer;click.edit()is never called).
- CVE-2026-7246 (HIGH): command injection in
Compatibility
- No schema, route, or contract change. MCP tools / Resources / Prompts unchanged (53 / 7 / 3).
- Pinned explicitly for reproducibility; dependency graph resolves cleanly (pip check / pip-audit green).
Tests
2491 passed (no change — dependency-only bump).
v1.33.20 — recon: graceful crt.sh timeout in domain report
Fix
Domain report no longer fails when crt.sh (Certificate Transparency) upstream times out.
full_domain_report (powering /v1/domain/{domain} and the audit_domain MCP tool) ran its certificate-transparency and subdomain lookups through two closures sharing one crt.sh fetch. When that upstream was slow, the inner timeout was left unhandled — the whole report failed with a 504 even though DNS, WHOIS, SSL, headers and threat data had all resolved successfully.
Now the timeout is caught inside both closures and the report degrades gracefully: it returns 200 with the partial result, and both the certificates and subdomains branches honestly report crtsh_status: "timeout" (instead of one of them masquerading as "ok" with an empty list). Clients get every reachable signal plus a truthful availability flag for the one source that was slow.
Compatibility
- No schema change.
errorandcrtsh_statusfields already existed. - Backward compatible. New optional
crtsh_errorparameter on internal helpers defaults to preserving prior behavior. - Status code for the crt.sh-timeout path changes 504 → 200 (partial success).
Tests
2490 → 2491 (added one regression test covering the crt.sh-timeout path on both branches).
MCP tools / Resources / Prompts unchanged (53 / 7 / 3).
v1.33.18 — Correct field types in MCP outputSchema
Fixes #38 — MCP outputSchema field-type accuracy
The lean outputSchema advertised in tools/list previously declared nearly every field as {"type":"object"}, regardless of the field's real value type, because optional fields (T | None) are encoded as anyOf in the source schema and the flattener only inspected a top-level type key. Strict MCP clients (e.g. opencode/dcp) rejected valid tool responses whose values were strings, arrays, numbers, or booleans.
Fix: resolve the real primitive type from the schema's non-null union arm (and one-hop $ref) while keeping the advertised schema flat (no $defs/$ref/anyOf). Fields with no single representable type (mixed-type unions or Any) now emit a permissive schema that validates any value instead of a wrong object type. Hardened against cyclic schema definitions.
Compatibility: wire-compatible — stricter clients now accept responses; lenient clients are unaffected. No tool or argument changes.
- MCP surface unchanged: 53 tools, 7 Resources, 3 Prompts
- Adds 13 schema tests (field-type + edge-case + cycle-guard); suite at 2486 passing
Follow-on patch to v1.33.17.
v1.33.14 — Lean outputSchema on tools/list (recover Smithery quality)
Lean (flat) outputSchema reintroduced on tools/list
v1.33.13 stripped outputSchema entirely to fix a Smithery catalog-gateway availability issue (309KB→81KB) — but that dropped Smithery's "Output schemas" quality criterion to 0/53 (−10.37pt).
This release reintroduces a lean, flat outputSchema per tool: the success model's top-level field names + primitive types only (no $defs/$ref/anyOf/prose, ~0.5KB/tool). Each tool re-advertises its output shape and the whole tools/list payload stays at ~104.5KB — well under the gateway buffer.
Changes
- New
_leanify_output_schema()transform in the MCP proxy (wire-only; never touches the FastMCP tool objects). Applied on both the fast-path cache and the lazy-rebuild path. requiredis filtered to advertised properties (valid JSON Schema).tools/callvalidation +structuredContentare runtime concerns — unaffected.
Verification
tools/list(prod): 53/53 tools carry a flatoutputSchema, payload 104.5KB, no$refon the wire.- Tests: 2467 passed (test_mcp.py flips ABSENT→PRESENT+FLAT invariants + per-tool/payload budgets).
- MCP tools/Resources/Prompts counts unchanged (53/7/3).
v1.33.13 — tools/list payload slim (Smithery availability fix)
Performance / contract — MCP tools/list
Symptom: Smithery Observability reported tools/list 100% Unavailable (transport-level drop, 0% server/client errors) while tools/call worked normally. RPC traffic via Smithery collapsed.
Root cause: the tools/list response had grown to ~309 KB, of which ~73% was outputSchema (FastMCP-derived from Pydantic return models). The catalog gateway could not buffer the oversized body and dropped it.
Fix: stop emitting outputSchema on the wire. It is OPTIONAL per the MCP spec; the call contract (name + description + inputSchema) is fully preserved, and tools/call runtime validation + structuredContent are unaffected. Removed the now-orphaned _slim_output_schema helper (the earlier annotation-only slim kept the 231 KB structure).
Result: tools/list payload 309 KB → 81 KB (~73% reduction), 53 tools, 0 with outputSchema. Production verified.
- VERSION 1.33.12 → 1.33.13 (cache-prefix invalidation)
- Tests: 2467 passed (test invariant flipped: outputSchema must be absent + payload < 120 KB on fast-path and cache-None paths)
- MCP tools/Resources/Prompts counts unchanged (53 / 7 / 3)
v1.33.12 — httpx pool-leak hotfix (S253 reopen)
Hotfix on v1.33.11 — restores /v1/tech, /v1/scan/headers, /v1/domain
A regression of the v1.33.8 _ssrf_http pool-leak class was observed in production
(36-minute PoolTimeout cluster on worker 2805645, 19 May 22:02 UTC) causing
intermittent 504s on three domain-intelligence endpoints. v1.33.10 only suppressed
the "Task exception was never retrieved" log noise; the underlying slot leak
remained. v1.33.12 closes both root causes.
Fixes
-
fetch_live_headersrace-and-cancel leak (primary): parallel HTTPS+HTTP
.get()race cancelled the losing task mid-flight; httpcore never returned the
pool slot. Refactored to sequential HTTPS-first / HTTP-fallback, mirroring the
v1.33.7fetch_live_pagepattern. No second task, no cancel, slot always
returned. -
full_domain_reportorphan-task storm (amplifier): when an earlyawait
raised (e.g.f_subsTimeoutErroron slowcrt.sh), the trailing
create_taskhandles (f_certs,f_threat,f_whois,f_ab,f_sh,
f_headers) were neverawaited or cancelled — they leaked into the event
loop and held pool slots. Wrapped the await chain intry/finallythat
cancels + drains any pending task on exit. WAF detection moved inside the
guarded scope sof_headersis read before cleanup cancels it.
Status-code change for affected paths
| Endpoint | Pre (v1.33.11) | Post (v1.33.12) |
|---|---|---|
/v1/tech/{domain} |
504 ~13s (intermittent) | 200 ~0.5s |
/v1/scan/headers/{domain} |
504 ~5s (intermittent) | 200 ~0.5s |
/v1/domain/{domain} |
504 (intermittent under load) | 200 |
No request/response shape change; only the failure mode is removed.
Tests
TestFetchLiveHeadersSequential(3) — happy-path call_count=1, HTTP fallback ordering, both-fail error dict.TestFullDomainReportOrphanCleanup(1) — early-timeout regression, asserts no orphan tasks remain after exception unwind.- Full suite: 2463 → 2467 passed.
Fold-in
- CodeQL #111/#112/#113 (Empty-except): added intent comments inside the three
PRAGMA busy_timeout=5000reset blocks inapp/db.py— the unit-cleanup path
must never mask the unit's primary error.
Follows
- v1.33.11 (sigma bulk per-item quota + reflected-echo fix)
- v1.33.10 (GHSA delta-sync self-pin fix + S253 resilience batch)
- v1.33.8 (pattern-B streaming-cancel pool-leak hardening — original S253 close)