Add sandbox flag + per-key à-la-carte scopes (payment-connect foundation)
Foundation for agent-delegable payment-provider connect (plans/agent-payment-connect-scope.md, slices 1-2 of 5). Not yet wired to any connect endpoint — the gate (require_provider_connect + BTCPay non-mainnet network check) is a follow-up. - Config.sandbox_mode from KEYSAT_SANDBOX_MODE (daemon-level, never settable via any API); surfaced read-only in /v1/admin/tier as "sandbox". - Migration 0024: additive scoped_api_keys.extra_scopes column (JSON array). - Per-key à-la-carte scopes: require_scope grants via role OR a key's extra_scopes; GRANTABLE_EXTRA_SCOPES allowlist (payment_providers:write only), validated on create and echoed in create/list responses. - payment_providers:write is in NO role: grants() carves the à-la-carte set out of full-admin's wildcard, so even a scoped full-admin key can't reach it through its role — only a per-key grant does. extra_scopes parsing fails closed (NULL/malformed -> no grant). - Tests: invariant (no role grants the à-la-carte set), fail-closed parsing, create/list round-trip, reject ungrantable scope. Suite green: lib 13, api 59.
This commit is contained in:
@@ -162,6 +162,10 @@ pub async fn admin_status(
|
||||
Ok(axum::Json(serde_json::json!({
|
||||
"tier": tier.label,
|
||||
"tier_name": tier.display_name,
|
||||
// Daemon-level sandbox flag (env KEYSAT_SANDBOX_MODE, read-only here —
|
||||
// never settable via any API). The admin SPA renders a "SANDBOX"
|
||||
// banner on it; it also gates scoped payment-provider connect.
|
||||
"sandbox": state.config.sandbox_mode,
|
||||
"entitlements": tier.entitlements,
|
||||
"usage": {
|
||||
"products": product_count,
|
||||
|
||||
Reference in New Issue
Block a user