From aa709fb854a7144109dcba568267ac9ddf4dcddd Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 13 Sep 2026 22:11:49 +0200 Subject: [PATCH] Implement P05 checked services and safe selected delivery recovery Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c --- scripts/provider-onboarding-contract.py | 5 +++++ src/cmd/keycape/main.go | 1 + src/internal/adapters/privacyidea/adapter.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/scripts/provider-onboarding-contract.py b/scripts/provider-onboarding-contract.py index 2a55168..cdfeaee 100644 --- a/scripts/provider-onboarding-contract.py +++ b/scripts/provider-onboarding-contract.py @@ -89,6 +89,11 @@ def run(): time.sleep(3) code,_=req('GET','/token/',token=short) check('expired_provider_jwt_rejected',code==401) + fresh=login('alice','fixture-password','fixture') + code,_=req('GET','/token/',token=fresh) + check('new_provider_session_recovers_after_expiry',code==200) + code,_=req('GET','/token/',token=short) + check('expired_predecessor_stays_rejected',code==401) phase='platform_admin_recovery' from factor_recovery import ProviderStore,recover,RecoveryError with app.app_context(): diff --git a/src/cmd/keycape/main.go b/src/cmd/keycape/main.go index bf17c13..5f3b0c7 100644 --- a/src/cmd/keycape/main.go +++ b/src/cmd/keycape/main.go @@ -225,6 +225,7 @@ func main() { }}, readiness.Check{Name: "authelia", Probe: httpReachable(cfg.Authelia.TokenBaseURL, cfg.Authelia.BaseURL)}, readiness.Check{Name: "privacyidea", Probe: httpReachable(cfg.PrivacyIDEA.BaseURL)}, + readiness.Check{Name: "factor_reader", Probe: privacyIDEAAdapter.Probe}, )) // Liveness only: this says the process is up, and deliberately probes diff --git a/src/internal/adapters/privacyidea/adapter.go b/src/internal/adapters/privacyidea/adapter.go index adccfa4..35e6533 100644 --- a/src/internal/adapters/privacyidea/adapter.go +++ b/src/internal/adapters/privacyidea/adapter.go @@ -124,6 +124,11 @@ func (a *PrivacyIDEAAdapter) hasActiveToken(ctx context.Context, userID string) return false, nil } +// Probe checks the current mounted credential and realm visibility without reading a user factor. +func (a *PrivacyIDEAAdapter) Probe(ctx context.Context) error { + return a.verifyReadScope(ctx) +} + // verifyReadScope distinguishes no enrolled factor from lost realm visibility. // privacyIDEA returns a successful empty list for a reader with withdrawn rights. func (a *PrivacyIDEAAdapter) verifyReadScope(ctx context.Context) error {