Require fingerprint evidence for wakeup credential recovery

This commit is contained in:
Frank Song committed 2026-07-10 12:23:02 +08:00
1 parent 8eabf63049
commit 92ea69c7c3
2 files changed
+59 -2

No files matched your search

+6 -2
View File
@@ -1393,16 +1393,20 @@ def provider_has_process_wakeup_recovery_credential(provider_id: str, *, refresh
if not configured_fingerprint:
return False
has_unusable_pool_entry = False
has_unknown_unusable_pool_entry = False
for entry in _pool_entry_payloads(provider):
entry_fingerprint = _entry_secret_fingerprint(entry)
if not _pool_entry_currently_unusable(entry):
if entry_fingerprint == configured_fingerprint:
if entry_fingerprint and entry_fingerprint == configured_fingerprint:
return True
continue
has_unusable_pool_entry = True
if not entry_fingerprint:
has_unknown_unusable_pool_entry = True
continue
if entry_fingerprint == configured_fingerprint:
return False
return has_unusable_pool_entry
return has_unusable_pool_entry and not has_unknown_unusable_pool_entry
def _active_provider_id() -> str | None:
@@ -625,6 +625,59 @@ def test_process_wakeup_pause_keeps_pause_when_config_key_has_no_pool_evidence(t
assert saved.process_wakeup_pause["suppressed_count"] == 1
def test_process_wakeup_pause_keeps_pause_when_unusable_pool_entry_lacks_fingerprint(tmp_path, monkeypatch):
session = Session(
session_id="wakeup_pause_unusable_pool_entry_lacks_fingerprint",
workspace=str(tmp_path),
model="test-model",
model_provider="test-provider",
)
pause = models.record_process_wakeup_provider_unavailable_pause(
session,
classification="credential_pool_empty",
model="test-model",
provider="test-provider",
)
assert pause is not None
session.save()
models.SESSIONS[session.session_id] = session
monkeypatch.setattr(providers, "_get_provider_api_key", lambda _provider: "generic-config-key")
monkeypatch.setattr(
providers,
"_pool_entry_payloads",
lambda _provider: [{"last_status": "dead"}],
)
monkeypatch.setattr(
routes,
"provider_has_process_wakeup_recovery_credential",
providers.provider_has_process_wakeup_recovery_credential,
)
def _unexpected_start_run(*_args, **_kwargs):
raise AssertionError("unknown exhausted pool secret must not prove recovery")
monkeypatch.setattr(routes, "_resolve_chat_workspace_with_recovery", lambda _s, _w: str(tmp_path))
monkeypatch.setattr(routes, "_read_profile_model_config", lambda _s, _p: (None, None, {}))
monkeypatch.setattr(
routes,
"_resolve_compatible_session_model_state",
lambda *_args, **_kwargs: ("test-model", "test-provider", False),
)
monkeypatch.setattr(routes, "_start_run", _unexpected_start_run)
response = routes.start_session_turn(
session.session_id,
"[IMPORTANT: Background process completed with unknown exhausted pool key.]",
source="process_wakeup",
)
assert response["_status"] == 409
assert response["error"] == PROCESS_WAKEUP_PAUSE_ERROR
saved = Session.load(session.session_id)
assert saved is not None
assert saved.process_wakeup_pause["suppressed_count"] == 1
def test_process_wakeup_pause_clears_when_config_key_differs_from_exhausted_pool_secret(tmp_path, monkeypatch):
session = Session(
session_id="wakeup_pause_config_key_differs_from_exhausted_pool",