Manage defaults
Two keys, one default — switch it atomically, then disable with a replacement in one transaction.
The default flag decides which of your keys resolve serves. This scenario exercises its whole invariant: exactly one active default, atomic switches, and the disable-with-replacement move.
Goal
Hold two credentials for one provider, switch the default between them, and disable the default while promoting the other — never observing zero or two defaults along the way.
Prerequisites
- One active default credential (call it A) from scenario 02.
Steps
1. Add a second key — the default does not move by itself
Create credential B for the same provider without make_default. Expected 201 with is_default: false, and re-reading A shows it still holds the flag — only the owner's first credential defaults automatically.
Creating with the flag takes over, atomically
A create with make_default: true would instead demote A and arrive as the new default in one transaction — the same switch as step 2, just fused with creation. The documented 409 DEFAULT_CREDENTIAL_ALREADY_EXISTS is only the tiebreaker when two such creates race.
2. Switch the default to B
Call POST /v1/credentials/{B}/make-default with B's version:
curl -s -X POST "$CREDS_BASE/v1/credentials/$B_ID/make-default" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"version": 1}'
Expected 200 with is_default: true. Re-read A: its flag is gone — the switch happened in one transaction.
3. Disable B, promoting A in the same breath
Call POST /v1/credentials/{B}/disable with B's current version and replacement_default_id:
r = httpx.post(f"{CREDS_BASE}/v1/credentials/{b_id}/disable", headers=headers, json={
"version": b_version,
"replacement_default_id": a_id,
})
assert r.status_code == 200
assert r.json()["status"] == "disabled" and r.json()["is_default"] is False
Expected: B is disabled with no flag; A is active and the default again — one transaction, no gap without a default.
4. Re-enable B — the flag does not follow
Call POST /v1/credentials/{B}/enable. Expected 200, status: "active", but is_default: false — enable never restores the default; promotion stays explicit.
Verified by the test test_s04_manage_defaults.