fix(audit-2026-06-11/revocation-lag): evict PrincipalCache on credential change
The PrincipalCache (token-hash -> resolved Principal, 60s TTL) had no eviction hook, so deactivation / password change / API-key revocation flipped the DB rows but the cache kept serving the stale principal for up to the TTL window. Closes the audit's PrincipalCache revocation-lag Medium and greens authz::deactivating_user_revokes_their_api_keys. - PrincipalCache::evict_user(user_id) + evict_token(hash). - One shared cache Arc threaded into AuthState / AdminsState / ApiKeysState (a per-state cache would let the middleware's own copy keep authenticating a revoked principal). - Evict on: deactivation, password change (both evict_user), logout (evict_token, precise), single API-key delete (evict_user). - H-E1 note: DB-write invalidation stays best-effort by design (a blip must not undo the rotation); the cache evict is what makes it take effect on the next request. - Renamed bearer_and_cookie_produce_same_principal -> session_token_and_api_key_produce_same_principal (cookie auth was removed in C-1; the test never tested cookies). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -380,12 +380,14 @@ async fn member_can_only_touch_apps_they_belong_to(pool: PgPool) {
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 5. Bearer pic_ + cookie produce the same Principal
|
||||
// 5. Session-token bearer + pic_ API-key bearer produce the same Principal
|
||||
// (cookie auth was removed in the audit 2026-06-11 C-1 fix; both paths
|
||||
// now travel through the Authorization header).
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
|
||||
#[sqlx::test(migrations = "../manager-core/migrations")]
|
||||
async fn bearer_and_cookie_produce_same_principal(pool: PgPool) {
|
||||
async fn session_token_and_api_key_produce_same_principal(pool: PgPool) {
|
||||
let s = boot(pool).await;
|
||||
let session_token = login_token(&s.server, "owner", "owner-pw").await;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user