Implement verified public registration flow
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-08-10 11:26:18 +02:00
parent b7a57a50a4
commit c36a09bded
12 changed files with 610 additions and 7 deletions

View file

@ -55,6 +55,43 @@ class ProvisioningRequest:
idempotency_key: str
correlation_id: str
roles: tuple[str, ...] = ()
preferred_username: str | None = None
@dataclass(frozen=True)
class RegistrationVerificationRequest:
"""Non-secret request for an external mailbox-control challenge."""
registration_id: str
normalized_email: str
preferred_username: str
client_id: str
tenant: str
correlation_id: str
display_name: str | None = None
@dataclass(frozen=True)
class RegistrationVerificationReceipt:
"""Opaque receipt safe to use for correlation, not authentication."""
request_id: str
accepted: bool = True
@dataclass(frozen=True)
class VerifiedRegistrationApplicant:
"""Purpose-bound evidence returned after consuming a single-use handle."""
verification_id: str
registration_id: str
normalized_email: str
preferred_username: str
client_id: str
tenant: str
source_system: str
assurance: Mapping[str, Any]
display_name: str | None = None
@dataclass(frozen=True)
@ -133,6 +170,18 @@ class IdentityProvisioningPort(Protocol):
"""Converge managed provider state toward the requested lifecycle."""
class RegistrationVerificationPort(Protocol):
"""Mailbox verification issuer; token plaintext never enters domain state."""
def request(
self, request: RegistrationVerificationRequest
) -> RegistrationVerificationReceipt:
"""Request an anti-enumerating, purpose-bound verification message."""
def consume(self, opaque_handle: str) -> VerifiedRegistrationApplicant:
"""Atomically consume verified, unexpired applicant evidence."""
class UserEngineStore(Protocol):
"""Durable persistence boundary for user-engine service behavior.