aeat.application.workflow._models module¶
Strict pydantic v2 records for the composite workflow engine.
Every boundary-crossing type in aeat.application.workflow is
defined here as a frozen, strict, extra="forbid"
pydantic.BaseModel or as an enum.StrEnum for closed
enumerations. WorkflowStep.details is reserved for string-valued
diagnostics emitted by workflow diagnostics. Some helpers accept an
optional SecureObjectRepository so
callers can supply a custom storage backend without going through the runtime
default. The
WorkflowState record carries a reference to the active-bucket
TransactionCatalogueRepository when one is needed downstream.
This module uses WorkflowResult, WorkflowEngine,
and UserProfileRecord for workflow persistence and state management.
WorkflowEvent and the review-annotation field types embedded on
WorkflowState (InvoiceReviewRecord, LedgerReviewRecord) are
defined in the shared leaf module
aeat.application._workflow_review_models rather than here or in
aeat.application.review, because aeat.application.review embeds
WorkflowEvent as a field type in turn — a genuine mutual runtime
dependency that a shared leaf module resolves without either package
importing the other.
See also
WorkflowEngineProduces
WorkflowResultrecords and advancesWorkflowStagevalues.WorkflowPurposeSelects the local FILE or VERIFY policy that controls deadline and preflight treatment.
WorkflowRunRepositoryPersists terminal
WorkflowResultrecords in secure storage.WorkflowStateRepositoryPersists the encrypted
WorkflowStateenvelope.aeat.application.modelo._workflow_gateDrives calculation revisions through the workflow and persists the resulting run record before verification or local filing state changes.
Import ordering note¶
The SiteHealthStatus and ModeloDeadline imports are placed
after WorkflowState and related state models so that
aeat.application.auth._actions (which imports WorkflowState
from this partially-initialised module during the browser-adapter import
chain) finds those names already present.
- class WorkflowStage(*values)[source]¶
Bases:
StrEnumThe read-only stages of the composite workflow, in strict order.
- LOADING_PROFILE¶
- COMPUTING_DEADLINES¶
- CHECKING_INBOX¶
- BUILDING_DRAFT¶
- VALIDATING_DRAFT¶
- RUNNING_PREFLIGHT¶
- DONE¶
- ABORTED¶
- class WorkflowPurpose(*values)[source]¶
Bases:
StrEnumWhy the workflow engine is being driven.
The purpose decides whether the filing-window deadline is an abort gate or merely informational context:
FILE— the end-to-end filing pipeline (work fileand the end-to-endWorkflowEnginerun). Filing without a pending obligation is refused: theCOMPUTING_DEADLINESstage aborts withWorkflowAbortReason.NO_PENDING_OBLIGATIONwhen the schedule carries no matching obligation and withWorkflowAbortReason.DEADLINE_PASSEDwhen the obligation window has already closed.VERIFY— thework verifycalculation check. Verification asserts a calculation is internally sound against the registry’s verification expectations; it has no honest dependency on the AEAT filing calendar. TheCOMPUTING_DEADLINESstage records the filing-window state as informational context and never aborts on it, so a correct calculation can be confirmed early, offline, or for a past period.
- FILE¶
- VERIFY¶
- class WorkflowAbortReason(*values)[source]¶
Bases:
StrEnumClosed set of reasons the
WorkflowEnginemay abort a run.Each member maps to a distinct failure path in the engine’s stage sequence. CLI surfaces and audit logs carry the string value so operators and tools can key on it without importing this module.
- NO_PENDING_OBLIGATION¶
- INBOX_BLOCKING_REQUERIMIENTO¶
- DEADLINE_PASSED¶
- ALREADY_FILED¶
- DRAFT_HAS_ERRORS¶
- PREFLIGHT_FAILED¶
- CERT_INVALID¶
- USER_CANCELLED¶
- SITE_UNAVAILABLE¶
- UNHANDLED_EXCEPTION¶
- class DeclaracionPointer(**data)[source]¶
Bases:
BaseModelLightweight pointer to a persisted filing draft stored in
WorkflowState.Keyed in
WorkflowState.declarationsby the value returned fromdeclaration_key().draft_idandstatusare written by the workflow engine after each filing stage;exported_pathrecords the on-disk fichero-BOE path when the draft was exported;verifiedrecords the last verification verdict for thework verifycommand.- Parameters:
- modelo: str¶
- period: Period¶
- draft_id: str | None¶
- status: str | None¶
- exported_path: str | None¶
- verified: bool | None¶
- updated_at: datetime¶
- class ProfileBucketPointer(**data)[source]¶
Bases:
BaseModelPointer to a secure profile bucket.
bucket_idis the immutable UUIDv4 profile identity and the name of the bucket directory on disk.labelis the decoupled mutable operator-chosen display name read from the bucket manifest.statusis the plaintext lifecycle marker carried on the manifest; the live-surface scanners filter on it so a tombstoned profile never leaks intolist/switch/ name-uniqueness.- Parameters:
bucket_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=128, pattern=None, ascii_only=None)])
label (str)
status (BucketLifecycleStatus)
- bucket_id: BucketId¶
- label: str¶
- status: BucketLifecycleStatus¶
- declaration_key(modelo, period)[source]¶
Return the canonical state-store key for a
(modelo, period)pair.The period segment is stored as
filing_year:registry_tokenso declaration state never keys by a combined token such as2025Q1.
- class WorkflowState(**data)[source]¶
Bases:
BaseModelEncrypted operator state for the AEAT user CLI.
The entire state is persisted as a single encrypted envelope via
WorkflowStateRepository. Mutations always return a new copy (model_copy()) to preserve the frozen-model invariant.- Variables:
auth – Local AEAT access readiness state.
declarations – Filing draft pointers keyed by
declaration_key().invoice_reviews – Invoice review annotations keyed by
invoice_id.ledger_reviews – Ledger transaction review annotations keyed by
transaction_id.updated_at – UTC timestamp of the last write.
- Parameters:
auth (AuthState)
declarations (dict[str, DeclaracionPointer])
invoice_reviews (dict[str, InvoiceReviewRecord])
ledger_reviews (dict[str, LedgerReviewRecord])
bucket_events (tuple[WorkflowEvent, ...])
updated_at (datetime)
The historical
profilesfield has retired. Consumers that need to enumerate registered profiles callaeat.application.workflow._profile_bucket_scan.list_profile_buckets()orread_profile_bucket()directly; both scan<aeat_local_storage_root>/buckets/*/manifest.tomland never open an encrypted database. The active profile resolves via the precedence chain (Settings override > plaintext pointer file).- auth: AuthState¶
- declarations: dict[str, DeclaracionPointer]¶
- invoice_reviews: dict[str, InvoiceReviewRecord]¶
- ledger_reviews: dict[str, LedgerReviewRecord]¶
- bucket_events: tuple[WorkflowEvent, ...]¶
- updated_at: datetime¶
- active_profile_record(*, secure_objects=None, schema=None)[source]¶
Return the active
UserProfileRecordfrom its secure bucket.The active bucket id resolves via the precedence chain in
aeat.core.resolve_active_bucket_id()(env var > pointer file fallback). The bucket id and profile name are 1:1 by orchestration convention, so the resolved id is the lifecycle-service read key.secure_objects(aSecureObjectRepositoryoverride) andschemaare optional overrides forwarded tobuild_lifecycle_service(); a per-bucket store and the bundled schema are resolved whenNone.- Return type:
- Parameters:
secure_objects (SecureObjectRepository | None)
schema (ProfileSchemaDefinition | None)
- active_transaction_catalogue_repository(state, *, objects=None)[source]¶
Return the
TransactionCatalogueRepositoryfor the active profile bucket.- Parameters:
state (
WorkflowState) – The current workflow state used to resolve the active bucket.objects (
SecureObjectRepository|None) – OptionalSecureObjectRepositoryoverride passed through to the returned repository.
- Return type:
- update_declaration_pointer(state, *, modelo, period, draft_id=None, status=None, exported_path=None, verified=None)[source]¶
Return
statewith the declaration pointer upserted for(modelo, period).draft_idandstatusare optional: when omitted (None) on an update they leave the existing pointer’s value untouched rather than clobbering it, so a partial update (e.g. recording only anexported_path) is safe.Returns the updated
WorkflowStatewith the pointer recorded.- Return type:
- Parameters:
- class SiteHealthAlert(**data)[source]¶
Bases:
BaseModelWorkflow-side alert wrapping a
SiteHealthStatusobservation.Attached to a
WorkflowStepwhen the AEAT browser health-check adapter reports a non-nominal site status during a workflow run.stageidentifies the workflow stage that observed the alert;run_idties it to the enclosingWorkflowResult.- Parameters:
stage (WorkflowStage)
status (SiteHealthStatus)
run_id (str)
- stage: WorkflowStage¶
- status: SiteHealthStatus¶
- run_id: str¶
- class WorkflowStepDetails(**data)[source]¶
Bases:
BaseModelOperator-visible details attached to a workflow step.
Carries arbitrary string-keyed diagnostic values emitted by the workflow engine. The model is intentionally permissive (
extra='allow') so existing call sites can continue to pass free-form dicts; the boundary is now a typed pydantic record instead of an opaquedict[str, str], so a future PR can promote specific step kinds into a discriminated union without breaking the field type onWorkflowStep.Per-stage key catalogue (the documented contract external tools consuming
WorkflowResult.stepsmay rely on):Deadline checks:
{"modelo", "period", "closes_on"}.Draft / snapshot mismatch:
{"draft_id", "modelo", "period", "profile_tax_id", "schema_version"}.Calculation validation failure:
{"error_count"}and any issue-specific keys.AEAT certificate health:
{"provider_kind", "provider_operator_impact", "cert_not_after", "cert_severity", "cert_days_until_expiry"}.Site-health alerts:
{"status", "run_id"}.
New keys may be added by the engine without bumping the workflow schema version. Removal or rename is a breaking change and must be paired with a workflow schema-version bump.
Implements
__getitem__,__contains__, andgetso existing read-side code that treatsstep.detailslike aMapping[str, str]keeps working without per-call-site migration; the typed model now anchors the storage shape.Frozen and strict on the inner values to preserve the boundary-strictness guarantee on workflow diagnostics.
- Parameters:
extra_data (Any)
- class WorkflowStep(**data)[source]¶
Bases:
BaseModelA single step in a
WorkflowResult.- Parameters:
stage (WorkflowStage)
started_at (datetime)
ended_at (datetime | None)
success (bool | None)
summary (str)
details (Annotated[WorkflowStepDetails | Mapping[str, object] | None, BeforeValidator(func=~aeat.application.workflow._models._coerce_workflow_step_details, json_schema_input_type=PydanticUndefined)])
site_health_alert (SiteHealthAlert | None)
- stage: WorkflowStage¶
- started_at: datetime¶
- ended_at: datetime | None¶
- success: bool | None¶
- summary: str¶
- details: Annotated[WorkflowStepDetails | Mapping[str, object] | None, BeforeValidator(_coerce_workflow_step_details)]¶
- site_health_alert: SiteHealthAlert | None¶
- class WorkflowResult(**data)[source]¶
Bases:
BaseModelThe full result of one
WorkflowEngine.run_next()invocation.- Parameters:
run_id (str)
started_at (datetime)
ended_at (datetime)
final_stage (WorkflowStage)
aborted_reason (WorkflowAbortReason | None)
obligation (ModeloDeadline | None)
draft_id (str | None)
submission_id (str | None)
steps (tuple[WorkflowStep, ...])
summary (str)
resumed_from (str | None)
- run_id: str¶
- started_at: datetime¶
- ended_at: datetime¶
- final_stage: WorkflowStage¶
- aborted_reason: WorkflowAbortReason | None¶
- obligation: ModeloDeadline | None¶
- draft_id: str | None¶
- submission_id: str | None¶
- steps: tuple[WorkflowStep, ...]¶
- summary: str¶
- resumed_from: str | None¶