feat(audit): publish sequenced heartbeat and reconciliation evidence
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06ec5-7e2b-7743-ac08-719e1b0f42e2
This commit is contained in:
parent
fce60099c4
commit
b9349782f4
32 changed files with 839 additions and 111 deletions
|
|
@ -7,14 +7,20 @@ from qonto_assistant.audit import AuditLogger
|
|||
from qonto_assistant.contracts import ActorClaims
|
||||
from qonto_assistant.errors import PolicyDeniedError
|
||||
from qonto_assistant.flex_auth_client import FlexAuthCheckClient
|
||||
from qonto_assistant.live_authorization import DENY_LIVE_AUTHZ, DENY_TENANT_ROLE, LiveAuthorizationGate
|
||||
from qonto_assistant.live_authorization import (
|
||||
DENY_LIVE_AUTHZ,
|
||||
DENY_TENANT_ROLE,
|
||||
LiveAuthorizationGate,
|
||||
)
|
||||
from qonto_assistant.policy import PolicyEngine
|
||||
from qonto_assistant.qonto_client import FixtureQontoClient
|
||||
from qonto_assistant.rate_limits import ConcurrencyLimiter, RateLimiter
|
||||
from qonto_assistant.service import CapabilityService
|
||||
from qonto_assistant.tenant_engine_client import TenantEngineClient
|
||||
|
||||
POLICY_FILE = Path(__file__).resolve().parents[1] / "src" / "qonto_assistant" / "policy" / "qonto-v1.yaml"
|
||||
POLICY_FILE = (
|
||||
Path(__file__).resolve().parents[1] / "src" / "qonto_assistant" / "policy" / "qonto-v1.yaml"
|
||||
)
|
||||
FIXTURE_DIR = Path(__file__).resolve().parent / "fixtures" / "qonto"
|
||||
|
||||
|
||||
|
|
@ -24,16 +30,23 @@ def _claims(tenant_id: str = "tenant:friendly:binky") -> ActorClaims:
|
|||
|
||||
def _flex_auth_client(effect: str) -> FlexAuthCheckClient:
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
return httpx.Response(200, json={"id": "d-1", "effect": effect, "resource": {}, "subject": {}, "provenance": {}})
|
||||
return httpx.Response(
|
||||
200,
|
||||
json={"id": "d-1", "effect": effect, "resource": {}, "subject": {}, "provenance": {}},
|
||||
)
|
||||
|
||||
return FlexAuthCheckClient(base_url="https://flex-auth.test", transport=httpx.MockTransport(handler))
|
||||
return FlexAuthCheckClient(
|
||||
base_url="https://flex-auth.test", transport=httpx.MockTransport(handler)
|
||||
)
|
||||
|
||||
|
||||
def _tenant_engine_client(roles: list[str]) -> TenantEngineClient:
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
return httpx.Response(200, json={"tenant_id": "tenant:friendly:binky", "roles": roles})
|
||||
|
||||
return TenantEngineClient(base_url="https://tenant-engine.test", transport=httpx.MockTransport(handler))
|
||||
return TenantEngineClient(
|
||||
base_url="https://tenant-engine.test", transport=httpx.MockTransport(handler)
|
||||
)
|
||||
|
||||
|
||||
# --- Gate unit tests -------------------------------------------------------------------
|
||||
|
|
@ -95,7 +108,9 @@ def test_gate_denies_when_tenant_engine_unreachable() -> None:
|
|||
|
||||
gate = LiveAuthorizationGate(
|
||||
flex_auth_client=_flex_auth_client("allow"),
|
||||
tenant_engine_client=TenantEngineClient(base_url="https://tenant-engine.test", transport=httpx.MockTransport(handler)),
|
||||
tenant_engine_client=TenantEngineClient(
|
||||
base_url="https://tenant-engine.test", transport=httpx.MockTransport(handler)
|
||||
),
|
||||
required_tenant_roles=frozenset({"VEN"}),
|
||||
)
|
||||
|
||||
|
|
@ -108,7 +123,9 @@ def test_gate_denies_when_tenant_engine_unreachable() -> None:
|
|||
def _service(gate: LiveAuthorizationGate, events: list[dict[str, object]]) -> CapabilityService:
|
||||
return CapabilityService(
|
||||
client=FixtureQontoClient(fixture_dir=FIXTURE_DIR),
|
||||
policy=PolicyEngine.from_file(POLICY_FILE, required_scope="finance.qonto.read", enforce_scope=False),
|
||||
policy=PolicyEngine.from_file(
|
||||
POLICY_FILE, required_scope="finance.qonto.read", enforce_scope=False
|
||||
),
|
||||
audit_logger=AuditLogger(sink=events.append),
|
||||
rate_limiter=RateLimiter(limit=20, window_seconds=60),
|
||||
concurrency_limiter=ConcurrencyLimiter(limit=4),
|
||||
|
|
@ -151,7 +168,9 @@ def test_service_without_gate_configured_behaves_as_before() -> None:
|
|||
events: list[dict[str, object]] = []
|
||||
service = CapabilityService(
|
||||
client=FixtureQontoClient(fixture_dir=FIXTURE_DIR),
|
||||
policy=PolicyEngine.from_file(POLICY_FILE, required_scope="finance.qonto.read", enforce_scope=False),
|
||||
policy=PolicyEngine.from_file(
|
||||
POLICY_FILE, required_scope="finance.qonto.read", enforce_scope=False
|
||||
),
|
||||
audit_logger=AuditLogger(sink=events.append),
|
||||
rate_limiter=RateLimiter(limit=20, window_seconds=60),
|
||||
concurrency_limiter=ConcurrencyLimiter(limit=4),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue