from __future__ import annotations import re from typing import Literal from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, model_validator from .forge_secret_delivery import ForgeSecretDeliveryControllerArtifactV1 _REVISION = re.compile(r"^[0-9a-f]{40}$") _DIGEST = re.compile(r"^sha256:[0-9a-f]{64}$") _REQUEST = re.compile(r"^[0-9a-f]{64}$") _NONCE = re.compile(r"^[0-9a-f]{32}$") _JOB = re.compile(r"^forge-install-[0-9a-f]{64}$") _RUNTIME_SERVICES = ("api", "dashboard", "itworx-forge", "postgres", "worker") class ForgeRuntimeReadinessProfileV1(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True, strict=True) revision: StrictStr = Field(pattern=_REVISION.pattern) workspace_image_digest: StrictStr = Field(alias="workspaceImageDigest", pattern=_DIGEST.pattern) frontdoor_image_digest: StrictStr = Field(alias="frontdoorImageDigest", pattern=_DIGEST.pattern) class ForgeRuntimeServiceHealthV1(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True, strict=True) name: Literal["api", "dashboard", "itworx-forge", "postgres", "worker"] status: Literal["healthy", "not_ready", "unavailable"] class ForgeRuntimeHealthV1(BaseModel): model_config = ConfigDict(extra="forbid", frozen=True, strict=True) status: Literal["healthy", "not_ready", "unavailable"] services: list[ForgeRuntimeServiceHealthV1] @model_validator(mode="after") def fixed_service_set(self) -> ForgeRuntimeHealthV1: if tuple(item.name for item in self.services) != _RUNTIME_SERVICES: raise ValueError("runtime service set is invalid") return self class ForgeRuntimeReadinessV1(BaseModel): """Strict controller response for one fresh, fixed Forge observation.""" model_config = ConfigDict(extra="forbid", frozen=True, populate_by_name=True, strict=True) api_version: Literal["itworx.forge-runtime-readiness/v1"] = Field(alias="apiVersion") status: Literal["ready", "not_ready", "unavailable"] repository: Literal["jens/itworx-forge"] operation: Literal["forge_first_install"] request: StrictStr = Field(pattern=_REQUEST.pattern) profile: ForgeRuntimeReadinessProfileV1 observed_at: StrictInt = Field(alias="observedAt", ge=0) nonce: StrictStr = Field(pattern=_NONCE.pattern) health: ForgeRuntimeHealthV1 migration_completed: StrictBool = Field(alias="migrationCompleted") controller_artifact: ForgeSecretDeliveryControllerArtifactV1 = Field(alias="controllerArtifact") @model_validator(mode="after") def readiness_consistency(self) -> ForgeRuntimeReadinessV1: service_statuses = {item.status for item in self.health.services} expected_health = ( "unavailable" if "unavailable" in service_statuses else "not_ready" if "not_ready" in service_statuses else "healthy" ) valid_overall = ( self.status == "unavailable" if expected_health == "unavailable" else self.status in {"not_ready", "unavailable"} if expected_health == "not_ready" else self.status == "ready" if self.migration_completed else self.status in {"not_ready", "unavailable"} ) if self.health.status != expected_health or not valid_overall: raise ValueError("readiness status does not match current health proof") return self class ForgeRuntimeReadinessResultV1(BaseModel): """Bounded operator projection; upstream diagnostics and nonce are omitted.""" model_config = ConfigDict(extra="forbid", frozen=True, populate_by_name=True, strict=True) status: Literal["ready", "not_ready", "unavailable"] message: Literal[ "forge_runtime_ready", "forge_runtime_not_ready", "forge_runtime_readiness_unavailable", ] target: Literal["itworx-forge"] = "itworx-forge" job_id: StrictStr | None = Field(default=None, alias="jobId", pattern=_JOB.pattern) revision: StrictStr | None = Field(default=None, pattern=_REVISION.pattern) workspace_image_digest: StrictStr | None = Field( default=None, alias="workspaceImageDigest", pattern=_DIGEST.pattern ) frontdoor_image_digest: StrictStr | None = Field( default=None, alias="frontdoorImageDigest", pattern=_DIGEST.pattern ) observed_at: StrictInt | None = Field(default=None, alias="observedAt", ge=0) health: ForgeRuntimeHealthV1 migration_completed: StrictBool = Field(default=False, alias="migrationCompleted") controller_artifact: ForgeSecretDeliveryControllerArtifactV1 | None = Field( default=None, alias="controllerArtifact" ) @model_validator(mode="after") def public_status_message(self) -> ForgeRuntimeReadinessResultV1: expected = { "ready": "forge_runtime_ready", "not_ready": "forge_runtime_not_ready", "unavailable": "forge_runtime_readiness_unavailable", }[self.status] if self.message != expected: raise ValueError("readiness message does not match status") service_statuses = {item.status for item in self.health.services} expected_health = ( "unavailable" if "unavailable" in service_statuses else "not_ready" if "not_ready" in service_statuses else "healthy" ) valid_overall = ( self.status == "unavailable" if expected_health == "unavailable" else self.status in {"not_ready", "unavailable"} if expected_health == "not_ready" else self.status == "ready" if self.migration_completed else self.status in {"not_ready", "unavailable"} ) if self.health.status != expected_health or not valid_overall: raise ValueError("public readiness is inconsistent") identity_fields = ( self.job_id, self.revision, self.workspace_image_digest, self.frontdoor_image_digest, self.observed_at, self.controller_artifact, ) if self.job_id is None and ( self.status != "unavailable" or any(value is not None for value in identity_fields[1:]) ): raise ValueError("public readiness identity is incomplete") if self.job_id is not None and any(value is None for value in identity_fields): raise ValueError("public readiness identity is incomplete") return self