feat: cloud adapters E2B/Modal and billing export (SAND-WP-0010)

Add credentialed E2B and Modal extensions, burst routing fallback,
fin-hub meter export hook, BYOK docs, and 77 tests.
This commit is contained in:
tegwick 2026-06-24 12:50:19 +02:00
parent 6d0a1a8b1e
commit 15f031fd65
26 changed files with 859 additions and 75 deletions

View file

@ -0,0 +1,49 @@
"""Optional fin-hub billing export for metered sandbox usage."""
from __future__ import annotations
import os
from typing import Any
import httpx
from sandboxer.models import MeterRecord, SandboxStatus
def fin_hub_url() -> str | None:
return os.environ.get("SANDBOXER_FIN_HUB_URL") or None
def export_meter_usage(
status: SandboxStatus,
*,
extension_id: str,
meter: MeterRecord,
) -> dict[str, Any] | None:
"""POST usage record to fin-hub when SANDBOXER_FIN_HUB_URL is set."""
if os.environ.get("SANDBOXER_NO_FIN_HUB", "").lower() in ("1", "true", "yes"):
return None
if meter.pricing_model != "metered" or not meter.actual_usd:
return None
base = fin_hub_url()
if not base:
return None
payload = {
"sandbox_id": status.sandbox_id,
"extension_id": extension_id,
"profile_id": status.profile_id,
"consumer": status.consumer.model_dump(),
"duration_s": meter.duration_s,
"actual_usd": meter.actual_usd,
"estimate_usd": meter.estimate_usd,
"currency": meter.currency,
}
try:
response = httpx.post(f"{base.rstrip('/')}/usage/sandbox", json=payload, timeout=10.0)
response.raise_for_status()
return response.json()
except httpx.HTTPError:
return None