"""TEN-WP-0011-T03: PIP claim freshness and live-lookup non-reentry.""" from __future__ import annotations from datetime import UTC, datetime from pathlib import Path import httpx import yaml from fastapi.testclient import TestClient from tenant_engine.app import create_app from tenant_engine.authz import FlexAuthWriteAuthorizer from tenant_engine.domain import CapabilityRole, Tenant, create_role_grant from tenant_engine.flex_auth import FlexAuthCheckClient from tenant_engine.store import InMemoryTenantStore ROOT = Path(__file__).resolve().parents[1] def test_pip_claims_contract_is_published(): data = yaml.safe_load((ROOT / "pip-claims.yaml").read_text()) assert data["role"] == "pip" classes = data["input_classes"] assert classes["tenant_roles_live"]["cross_request_cache_by_consumer"] is False assert classes["tenant_roles_live"]["request_scoped_memoization"] is True assert data["degradation"]["store_unavailable"]["http_status"] == 503 assert data["live_lookup_authorization"]["reenters_tenant_engine"] is False assert data["live_lookup_authorization"]["check_consumes_tenant_roles"] is False def test_live_lookup_hits_the_store_every_request(): store = InMemoryTenantStore() tenant = Tenant.create(tenant_id="t-1", identifier="tenant:friendly:binky") store.create_tenant(tenant) store.grant_role( create_role_grant( tenant=tenant, grant_id="g-1", role=CapabilityRole.CUS, grant_reason="manual_grant", plan_id=None, granted_by="ops", correlation_id="c-1", granted_at=datetime.now(UTC), ) ) calls = {"n": 0} original = store.active_roles def counting(tenant_id: str): calls["n"] += 1 return original(tenant_id) store.active_roles = counting # type: ignore[method-assign] from helpers import AllowAllAuthorizer client = TestClient(create_app(store=store, authorizer=AllowAllAuthorizer())) assert client.get("/tenants/t-1/roles/live", params={"actor": "flex-auth"}).status_code == 200 assert client.get("/tenants/t-1/roles/live", params={"actor": "flex-auth"}).status_code == 200 assert calls["n"] == 2 def test_live_lookup_check_does_not_reenter_tenant_engine(): """The authorize call for /roles/live POSTs /v1/check and never GETs us.""" seen: list[str] = [] def handler(request: httpx.Request) -> httpx.Response: seen.append(f"{request.method} {request.url.path}") return httpx.Response( 200, json={ "id": "d-live", "effect": "allow", "resource": {}, "subject": {}, "provenance": {}, }, ) store = InMemoryTenantStore() store.create_tenant(Tenant.create(tenant_id="t-1", identifier="tenant:friendly:binky")) client = FlexAuthCheckClient( base_url="https://flex-auth.example.test", transport=httpx.MockTransport(handler) ) app = create_app(store=store, authorizer=FlexAuthWriteAuthorizer(client=client)) response = TestClient(app).get("/tenants/t-1/roles/live", params={"actor": "flex-auth"}) assert response.status_code == 200 assert seen == ["POST /v1/check"] assert not any("/roles/live" in item for item in seen) assert not any("/tenants/" in item for item in seen)