generated from coulomb/repo-seed
Add credentialed E2B and Modal extensions, burst routing fallback, fin-hub meter export hook, BYOK docs, and 77 tests.
52 lines
1.6 KiB
Markdown
52 lines
1.6 KiB
Markdown
# Payments and metering
|
|
|
|
Version 0.1 — SAND-WP-0006. OpenRouter-style credits for metered SaaS extensions.
|
|
|
|
## Credits store
|
|
|
|
Path: `~/.local/share/sandboxer/credits.json` (override via test injection).
|
|
|
|
| Env | Default |
|
|
|-----|---------|
|
|
| `SANDBOXER_DEFAULT_CREDITS` | `10.0` USD on first use |
|
|
|
|
```bash
|
|
sandboxer credits show
|
|
sandboxer credits add 25.00
|
|
```
|
|
|
|
## Metered lifecycle
|
|
|
|
1. **create** — `estimate_cost` on metered extension; block if balance insufficient
|
|
2. **ready** — `SandboxStatus.meter.estimate_usd` recorded
|
|
3. **destroy** — `meter_actual` (or prorated estimate); debit credits; State Hub note event
|
|
|
|
Self-hosted extensions (`pricing_model: self-hosted`) skip credits.
|
|
|
|
## Extension contract
|
|
|
|
Metered extensions implement on `SandboxExtension`:
|
|
|
|
```python
|
|
def estimate_cost(self, profile, inputs, *, duration_s=3600) -> MeterQuote | None
|
|
def meter_actual(self, handle, *, duration_s: float) -> float | None
|
|
```
|
|
|
|
Reference: `ext.saas-stub` (no external API).
|
|
|
|
## BYOK
|
|
|
|
Provider API keys resolve at provision boundary — never stored on `SandboxStatus`
|
|
or emitted to State Hub.
|
|
|
|
1. Operator lookup: `warden route find "<provider> API key" --json`
|
|
2. Inject env before `sandboxer create` (e.g. `E2B_API_KEY`, `MODAL_TOKEN_ID`)
|
|
3. Or map `secret_ref` from extension config to `SANDBOXER_SECRET_<REF>` env
|
|
|
|
See `docs/cloud-adapters.md`.
|
|
|
|
## Billing export
|
|
|
|
On metered destroy, optional fin-hub hook when `SANDBOXER_FIN_HUB_URL` is set.
|
|
Posts `sandbox_id`, `extension_id`, `duration_s`, `actual_usd` to `/usage/sandbox`.
|
|
Implementation: `src/sandboxer/payments/billing_export.py`. |