Virgin Keys and Lock-In
How Athena learns caller IPs, when a key locks in, and how to promote or reset it.
Athena's lock-while-learning key type is called virgin_mode. It is designed
for cases where you know a key will eventually come from a small set of hosts,
but you do not want to hardcode that whitelist before first use.
This is the Athena feature most people mean when they ask about when a key "locks". The key is not disabled; it transitions from learning mode into normal whitelist enforcement.
State transitions
What happens during learning
While a key is both virgin_mode = true and virgin_resolved = false,
Athena's enforce_ip_policy path does this on every successful auth:
- writes or updates the caller IP in
api_key_ip_seen - increments
virgin_request_count - checks whether either lock-in threshold has been reached
- if a threshold is hit, promotes seen IPs and marks the key resolved
- allows the current request
That means unresolved virgin keys:
- still respect global and per-key blacklists
- do not yet apply global or per-key whitelist denials
- collect the observation data that later becomes the whitelist
When does the key lock in?
A virgin key locks in when either of these becomes true:
| Field | Meaning |
|---|---|
virgin_until_n_requests | lock after this many successful authentications |
max_whitelist_ips | lock after this many distinct seen IPs |
Important details from the implementation:
virgin_until_n_requests = 0disables the request-count threshold.max_whitelist_ips = 0disables the distinct-IP threshold and also means "no cap" when promoting seen IPs.- At least one of those values must be positive when
virgin_modeis enabled. - Athena uses whichever threshold is hit first.
Promotion behavior
When lock-in happens automatically, Athena:
- reads the earliest-seen rows from
api_key_ip_seen - inserts them into
api_key_ip_whitelist - uses
max_whitelist_ipsas the promotion cap when it is positive - marks the key
virgin_resolved = true - sets
locked_in = trueon the seen-IP rows
This is why a key that learned from three hosts can later reject a fourth host even though it worked during the learning window.
Constraints
POST /admin/api-keys rejects invalid virgin configurations:
- You cannot combine
virgin_modewith an initialip_whitelist. - You cannot combine
virgin_modewith an initialip_blacklist. - You must set at least one positive lock-in threshold.
Full create example
curl -X POST "http://localhost:4052/admin/api-keys" \
-H "X-Athena-Admin-Key: $ATHENA_KEY_12" \
-H "Content-Type: application/json" \
-d '{
"name": "bootstrap-worker",
"client_name": "analytics",
"rights": ["gateway.query"],
"virgin_mode": true,
"virgin_until_n_requests": 20,
"max_whitelist_ips": 3
}'Manual promote and reset
Promote immediately
Use this when you want to lock in before the threshold is reached.
curl -X POST "http://localhost:4052/admin/api-keys/$API_KEY_ID/virgin/promote" \
-H "X-Athena-Admin-Key: $ATHENA_KEY_12"Athena copies the earliest-seen IPs into the whitelist, respecting
max_whitelist_ips, then marks the key resolved.
Reset learning state
Use this when a deployment changes and the key needs to relearn.
curl -X POST "http://localhost:4052/admin/api-keys/$API_KEY_ID/virgin/reset" \
-H "X-Athena-Admin-Key: $ATHENA_KEY_12" \
-H "Content-Type: application/json" \
-d '{
"clear_seen": true
}'If clear_seen is false, Athena preserves the seen rows but clears their
locked_in flags. If it is true, the observation history is removed.
Inspecting what the key learned
curl "http://localhost:4052/admin/api-keys/$API_KEY_ID/ip-seen?limit=100" \
-H "X-Athena-Admin-Key: $ATHENA_KEY_12"The response includes hit_count, first_seen_at, last_seen_at, and
locked_in, which makes it easy to see exactly why a key locked when it did.