feat: implement onboarding journeys

This commit is contained in:
tegwick 2026-06-15 23:24:59 +02:00
parent 660ce24995
commit 5d7685dc8d
15 changed files with 1605 additions and 17 deletions

View file

@ -32,6 +32,12 @@ from user_engine.domain.models import (
ManagementMode,
Membership,
Mutability,
OnboardingJourney,
OnboardingJourneyStatus,
OnboardingStep,
OnboardingStepStatus,
OnboardingTask,
OnboardingTriggerType,
OutboxEvent,
PrincipalType,
PreparedAccount,
@ -45,9 +51,12 @@ from user_engine.domain.models import (
RegistrationSession,
RegistrationStatus,
Sensitivity,
SubsystemHandoff,
TenantAccount,
User,
Visibility,
WelcomeProtocol,
WelcomeProtocolStep,
new_id,
utc_now,
)
@ -84,6 +93,12 @@ __all__ = [
"ManagementMode",
"Membership",
"Mutability",
"OnboardingJourney",
"OnboardingJourneyStatus",
"OnboardingStep",
"OnboardingStepStatus",
"OnboardingTask",
"OnboardingTriggerType",
"OutboxEvent",
"PrincipalType",
"PreparedAccount",
@ -97,9 +112,12 @@ __all__ = [
"RegistrationSession",
"RegistrationStatus",
"Sensitivity",
"SubsystemHandoff",
"TenantAccount",
"User",
"Visibility",
"WelcomeProtocol",
"WelcomeProtocolStep",
"new_id",
"utc_now",
]

View file

@ -101,6 +101,32 @@ class AccessScopeType(StrEnum):
GROUP = "group"
class OnboardingTriggerType(StrEnum):
REGISTRATION = "registration"
PREPARED_ACCOUNT = "prepared_account"
INVITATION = "invitation"
ACCESS_PROFILE = "access_profile"
MANUAL = "manual"
class OnboardingJourneyStatus(StrEnum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
BLOCKED = "blocked"
COMPLETED = "completed"
SKIPPED = "skipped"
FAILED = "failed"
class OnboardingStepStatus(StrEnum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
BLOCKED = "blocked"
COMPLETED = "completed"
SKIPPED = "skipped"
FAILED = "failed"
class ProfileScope(StrEnum):
GLOBAL = "global"
TENANT = "tenant"
@ -375,6 +401,91 @@ class AccessControlFact:
source_system: str = "user-engine"
@dataclass(frozen=True)
class OnboardingTask:
subsystem: str
task_kind: str
task_id: str = field(default_factory=lambda: new_id("otask"))
external_ref: str | None = None
status: OnboardingStepStatus = OnboardingStepStatus.PENDING
@dataclass(frozen=True)
class SubsystemHandoff:
subsystem: str
handoff_id: str = field(default_factory=lambda: new_id("hnd"))
callback_ref: str | None = None
lifecycle_gap: str | None = None
status: OnboardingStepStatus = OnboardingStepStatus.PENDING
@dataclass(frozen=True)
class WelcomeProtocolStep:
step_key: str
title: str
subsystem: str
task_kind: str = "welcome"
task_ref: str | None = None
callback_ref: str | None = None
support_ref: str | None = None
requires_subsystem_callback: bool = False
@dataclass(frozen=True)
class WelcomeProtocol:
tenant: str
name: str
trigger_type: OnboardingTriggerType
steps: tuple[WelcomeProtocolStep, ...]
protocol_id: str = field(default_factory=lambda: new_id("wpro"))
journey_key: str | None = None
registration_status: RegistrationStatus | None = None
prepared_journey: str | None = None
application_id: str | None = None
realm_id: str | None = None
service_id: str | None = None
role: str | None = None
hat: str | None = None
required_factor_types: tuple[IdentityFactorType, ...] = ()
created_at: datetime = field(default_factory=utc_now)
updated_at: datetime = field(default_factory=utc_now)
@dataclass(frozen=True)
class OnboardingStep:
step_key: str
title: str
subsystem: str
step_id: str = field(default_factory=lambda: new_id("ostep"))
status: OnboardingStepStatus = OnboardingStepStatus.PENDING
task: OnboardingTask | None = None
handoff: SubsystemHandoff | None = None
support_ref: str | None = None
lifecycle_gap: str | None = None
updated_at: datetime = field(default_factory=utc_now)
@dataclass(frozen=True)
class OnboardingJourney:
tenant: str
user_id: str
protocol_id: str
trigger_type: OnboardingTriggerType
steps: tuple[OnboardingStep, ...]
journey_id: str = field(default_factory=lambda: new_id("ojrn"))
status: OnboardingJourneyStatus = OnboardingJourneyStatus.PENDING
source_id: str | None = None
source_event_type: str | None = None
journey_key: str | None = None
active_step_key: str | None = None
correlation_id: str | None = None
created_at: datetime = field(default_factory=utc_now)
updated_at: datetime = field(default_factory=utc_now)
completed_at: datetime | None = None
failed_at: datetime | None = None
skipped_at: datetime | None = None
@dataclass(frozen=True)
class FamilyMemberSpec:
primary_email: str