M21: add optional organisation identity

This commit is contained in:
NuklearRabbit
2026-08-10 15:35:25 +02:00
parent 509cb95110
commit c3f1cfc699
38 changed files with 563 additions and 110 deletions
+1 -3
View File
@@ -66,9 +66,7 @@ def test_return_registered_audit_event_exposes_before_after_and_link(ops_client)
)
key = "test-audit-before-after-001"
events = ops_client.get(
"/api/v1/audit", params={"action": "return_registered"}
).json()
events = ops_client.get("/api/v1/audit", params={"action": "return_registered"}).json()
event = next(e for e in events if e["metadata"]["idempotency_key"] == key)
assert event["before"] == {"status": "active"}
assert event["after"]["status"] == "returned"
+43 -3
View File
@@ -4,6 +4,48 @@ def test_unauthenticated_dashboard_is_rejected(client):
assert response.json()["error"]["code"] == "401"
def test_oidc_status_is_disabled_without_configuration(client):
assert client.get("/api/v1/auth/oidc/status").json() == {
"enabled": False,
"provider_name": None,
}
assert client.get("/api/v1/auth/oidc/login").status_code == 404
def test_oidc_callback_auto_provisions_and_logs_in(client, monkeypatch):
import app.api.routers.auth as auth_router
class FakeClient:
async def authorize_access_token(self, _request):
return {
"userinfo": {
"sub": "external-subject-1",
"email": "oidc.user@example.test",
"email_verified": True,
"name": "OIDC User",
}
}
class FakeOAuth:
def create_client(self, _name):
return FakeClient()
monkeypatch.setattr(auth_router.settings, "oidc_enabled", True)
monkeypatch.setattr(auth_router.settings, "oidc_issuer_url", "https://id.example.test")
monkeypatch.setattr(auth_router.settings, "oidc_client_id", "client")
monkeypatch.setattr(auth_router.settings, "oidc_client_secret", "secret")
monkeypatch.setattr(auth_router.settings, "oidc_allowed_email_domains", "example.test")
monkeypatch.setattr(auth_router, "oauth", FakeOAuth())
response = client.get("/api/v1/auth/oidc/callback", follow_redirects=False)
assert response.status_code == 307
assert response.headers["location"].endswith("/dashboard")
session = client.get("/api/v1/auth/session")
assert session.status_code == 200
assert session.json()["display_name"] == "OIDC User"
assert session.json()["role"] == "rental_employee"
def test_demo_login_grants_access(ops_client):
response = ops_client.get("/api/v1/dashboard")
assert response.status_code == 200
@@ -83,9 +125,7 @@ def test_logout_rejects_a_cookie_even_if_the_browser_retains_it(ops_client):
ops_client.cookies.clear()
# A fresh login in the same second receives a distinct signed token and remains valid.
fresh_login = ops_client.post(
"/api/v1/demo/login", json={"role": "operations_manager"}
)
fresh_login = ops_client.post("/api/v1/demo/login", json={"role": "operations_manager"})
assert fresh_login.status_code == 200
assert ops_client.get("/api/v1/auth/session").status_code == 200
+2 -6
View File
@@ -65,9 +65,7 @@ def test_attention_vehicles_respects_limit(client):
def test_vehicle_details_known_ref(client):
response = client.get(
"/api/v1/integrations/mcp/vehicles/MO-016", headers=_headers()
)
response = client.get("/api/v1/integrations/mcp/vehicles/MO-016", headers=_headers())
assert response.status_code == 200
body = response.json()
assert body["public_ref"] == "MO-016"
@@ -75,9 +73,7 @@ def test_vehicle_details_known_ref(client):
def test_vehicle_details_unknown_ref_is_404(client):
response = client.get(
"/api/v1/integrations/mcp/vehicles/MO-999", headers=_headers()
)
response = client.get("/api/v1/integrations/mcp/vehicles/MO-999", headers=_headers())
assert response.status_code == 404
+1 -3
View File
@@ -56,9 +56,7 @@ def test_seed_demo_scenarios_present():
assert duplicate_issue is not None
assert duplicate_issue.rule_type == "possible_duplicate_customer"
failed_run = db.scalar(
select(OutboxEvent).where(OutboxEvent.delivery_status == "failed")
)
failed_run = db.scalar(select(OutboxEvent).where(OutboxEvent.delivery_status == "failed"))
assert failed_run is not None
finally:
db.close()
+2 -6
View File
@@ -36,9 +36,7 @@ def _facts(**overrides) -> VehicleStatusFacts:
def test_available_with_active_rental_recommends_rented():
result = evaluate_vehicle_status(
_vehicle("available"), _facts(active_booking_refs=["BK-0001"])
)
result = evaluate_vehicle_status(_vehicle("available"), _facts(active_booking_refs=["BK-0001"]))
assert result.recommended_status == "rented"
assert result.recommendation_code == RECOMMENDATION_CODE_ACTIVE_RENTAL
assert result.safe_to_apply is True
@@ -83,9 +81,7 @@ def test_rented_with_no_active_booking_recommends_available():
def test_service_threshold_reached_recommends_maintenance():
result = evaluate_vehicle_status(
_vehicle("available"), _facts(service_threshold_reached=True)
)
result = evaluate_vehicle_status(_vehicle("available"), _facts(service_threshold_reached=True))
assert result.recommended_status == "maintenance"
assert result.recommendation_code == RECOMMENDATION_CODE_SERVICE_THRESHOLD
+1 -3
View File
@@ -52,9 +52,7 @@ def test_retry_failed_run_moves_to_pending_and_audits(ops_client):
def test_retry_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/workflows/00000000-0000-4000-8000-000000000020/retry"
)
response = employee_client.post("/api/v1/workflows/00000000-0000-4000-8000-000000000020/retry")
assert response.status_code == 403