platform
Sub-keys & spend caps
A sub-key delegates a slice of a stored provider credential: a strict device allowlist, a hard dollar cap, an expiry, and one-click revocation. The root credential never leaves the vault.
Minting a sub-key
sub = cs.vault.create_sub_key(parent="ibm-production",label="student:jane_doe",spend_cap_usd=25.00,allowed_devices=["ibm:brisbane", "simulator:*"],cap_hit_behavior="HARD_BLOCK",expires_at="2026-12-15T23:59:59Z",)print(sub.token) # cs_sub_... — shown exactly onceprint(sub.token_hint) # cs_...b5c4
Scope narrowing is enforced server-side
A sub-key's allowlist must be a strict subset of the parent credential's device allowlist. A mint or update that requests a device the parent doesn't allow is rejected with SUBKEY_SCOPE_EXCEEDS_PARENT (422) — this is a server-side guarantee, not a client convention.
Reserve-then-reconcile accounting
When a job is submitted, its estimated cost is reserved against the sub-key in a PostgreSQL transaction before dispatch; on completion, the reservation converts to actual spend. Concurrency-safe: fifteen students submitting at once cannot collectively blow past the cap. Reservations auto-expire if a worker crashes, so funds never leak.
spent_usd + reserved_usd + estimated_cost <= spend_cap_usd├─ true → reserve funds, queue run, 202 Accepted└─ false → SUBKEY_SPEND_CAP_EXCEEDED (402)
cap_hit_behavior is either HARD_BLOCK (reject the job) or NOTIFY_CONTINUE (alert the admin, proceed).
Bulk issuance for classrooms
batch = cs.vault.create_sub_keys(parent="ibm-production",defaults={"spend_cap_usd": 25.00,"allowed_devices": ["ibm:brisbane", "simulator:*"],"cap_hit_behavior": "HARD_BLOCK",},keys=[{"label": "student:jane_doe"},{"label": "student:john_smith"},{"label": "student:alice_chen", "spend_cap_usd": 50.00},],)
Atomic — if any key in the batch violates scope, the entire batch is rejected. Per-key overrides merge with the defaults.