Source code for cadrumo.application.user_profile.commands
"""Pydantic command and result contracts for the user-profile boundary.Import these contracts directly from this defining module. Keeping the Pydanticrecords together makes their validation dependency explicit without making the``user_profile`` package namespace a second public API."""from__future__importannotationsfromtypingimportAnnotated,SelffrompydanticimportBaseModel,Field,model_validatorfrom...core.errors.hierarchyimportpydantic_validation_boundaryfrom...core.errors.severityimportBaseSeverityas_BaseSeverityfrom...core.filing_yearimportFilingYearfrom...core.identity.profileimportProfileIdfrom...core.modelsimportSTRICT_FROZEN_CONFIGas_STRICT_FROZENfrom...core.periodimportPeriodfrom...core.prose_elisionimportElidedProsefrom...domain.calculations.registry.idsimportRevisionId__all__=["ProfilePreflightReport","ProfilePreflightRequirement","ProfileValidationIssue","ProfileValidationReport",]# ---------------------------------------------------------------------------# Validation and preflight# ---------------------------------------------------------------------------#: The validation-issue ``message`` annotation: elides rather than refusing.#:#: Every one of these is assembled from profile data — field paths, declared#: values, the set of modelos a gap affects — so its length belongs to the#: taxpayer's configuration, not to the author. Refusing the issue would fail#: the very validation pass that exists to report the problem._IssueMessage=Annotated[str,ElidedProse(512)]
[docs]classProfileValidationIssue(BaseModel):"""One validation finding raised against a profile snapshot."""model_config=_STRICT_FROZENseverity:_BaseSeveritycode:str=Field(min_length=1,max_length=64)path:str|None=Nonemessage:_IssueMessage
[docs]classProfileValidationReport(BaseModel):"""Aggregate validation report for a profile or a registration command."""model_config=_STRICT_FROZENprofile_id:ProfileIdschema_version:int=Field(ge=1)issues:tuple[ProfileValidationIssue,...]=()
[docs]classProfilePreflightRequirement(BaseModel):"""One required-but-missing profile selector for a modelo / revision."""model_config=_STRICT_FROZENselector:str=Field(min_length=1,max_length=128)section_key:str=Field(min_length=1,max_length=64)field_key:str=Field(min_length=1,max_length=128)label:str=Field(min_length=1,max_length=512)legal_refs:tuple[str,...]=()modelos:tuple[str,...]=()
[docs]classProfilePreflightReport(BaseModel):"""Per-`(modelo, revision, filing_year, period)` profile readiness report."""model_config=_STRICT_FROZENprofile_id:ProfileIdmodelo:str=Field(min_length=1,max_length=16)revision_id:RevisionId=Field(min_length=1,max_length=64)filing_year:FilingYearperiod:Periodmissing:tuple[ProfilePreflightRequirement,...]=()ready:bool#: Whether the per-operation axis actually assessed anything for this modelo#: — that is, whether any schema field declaring ``required`` also declared a#: ``modelo_<code>`` selector matching it. When false, no schema-required#: field was examined, so ``ready`` reports only the export-identity and#: conditional checks and MUST NOT be read as a clean bill of health.#: Deliberately carries no default: the single producer states it, and a#: default would silently assert an assessment that never ran.per_operation_requirements_assessed:bool@model_validator(mode="after")@pydantic_validation_boundarydef_period_matches_filing_year(self)->Self:ifself.period.filing_year!=self.filing_year:raiseValueError("filing_year must match period.filing_year")returnself