Implement user-engine portal foundation
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s

This commit is contained in:
tegwick 2026-07-27 22:45:42 +02:00
parent 60446e8b40
commit 0980d1fd41
12 changed files with 676 additions and 6 deletions

View file

@ -8,6 +8,7 @@ adapters without changing domain code.
from __future__ import annotations
from contextlib import AbstractContextManager
from dataclasses import dataclass
from typing import Any, Iterable, Mapping, Protocol
from user_engine.domain import (
@ -39,6 +40,52 @@ from user_engine.domain import (
)
@dataclass(frozen=True)
class ProvisioningRequest:
"""Provider-neutral identity lifecycle request.
``idempotency_key`` is mandatory so provider adapters can safely resume
after timeouts without creating duplicate directory identities.
"""
user_id: str
tenant: str
primary_email: str | None
display_name: str | None
idempotency_key: str
correlation_id: str
@dataclass(frozen=True)
class ProvisioningResult:
provider: str
external_subject: str
status: str
resumed: bool = False
class IdentityProvisioningPort(Protocol):
"""Lifecycle seam owned by NetKingdom adapters, not the user domain."""
def provision(self, request: ProvisioningRequest) -> ProvisioningResult:
"""Create or resume an external login identity."""
def suspend(
self, *, external_subject: str, idempotency_key: str, correlation_id: str
) -> ProvisioningResult:
"""Disable authentication while retaining recoverable identity state."""
def reactivate(
self, *, external_subject: str, idempotency_key: str, correlation_id: str
) -> ProvisioningResult:
"""Re-enable a previously suspended identity."""
def deprovision(
self, *, external_subject: str, idempotency_key: str, correlation_id: str
) -> ProvisioningResult:
"""Remove or tombstone an identity according to provider policy."""
class UserEngineStore(Protocol):
"""Durable persistence boundary for user-engine service behavior.