TEN-WP-0002 T01-T03: service skeleton, domain model, storage layer
Python 3.12 + FastAPI, pyproject.toml + Makefile mirroring
qonto-assistant's exactly. src/tenant_engine/{domain,store,app,main}.py:
- domain.py: Tenant, CapabilityRole (PLTF/IAM/VEN/CUS), RoleGrant,
PlanAssignment, create_role_grant() enforcing ADR-0014's invariants.
Refinement made while implementing: platform_default grants are valid
for trial-grouped tenants OR the reserved tenant:platform/tenant:coulomb
tenants (their baseline roles were never purchased either) -- the task
spec only named the trial case.
- store.py: TenantStore Protocol + InMemoryTenantStore, every mutation
emits a DomainEvent per the boundary contract's Audit Correlation
Contract.
- app.py/main.py: FastAPI factory + /health endpoint, verified live on
127.0.0.1:8090.
29 tests passing, including non-exclusive role coexistence (CUS+VEN
simultaneously) and append-only revoke semantics.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:01:23 +02:00
|
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
|
|
|
|
from tenant_engine.app import create_app
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_health_endpoint() -> None:
|
|
|
|
|
client = TestClient(create_app())
|
|
|
|
|
response = client.get("/health")
|
|
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
body = response.json()
|
|
|
|
|
assert body["status"] == "ok"
|
|
|
|
|
assert body["service"] == "tenant-engine"
|
2026-08-19 14:42:01 +02:00
|
|
|
assert body["store_backend"] == "memory"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_liveness_endpoint_does_not_depend_on_the_store() -> None:
|
|
|
|
|
class _UnavailableStore:
|
|
|
|
|
def ping(self) -> None:
|
|
|
|
|
raise AssertionError("liveness must not touch the store")
|
|
|
|
|
|
|
|
|
|
client = TestClient(create_app(store=_UnavailableStore()))
|
|
|
|
|
response = client.get("/live")
|
|
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
assert response.json()["status"] == "ok"
|