ψcatstate

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

mint_sub_key.pypy
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 once
print(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.

cap enforcementtxt
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

bulk_issue.pypy
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.