cadrumo.domain.calculations.registry.schema_extraction module

Extraction-profile schema contracts for registry revisions.

These RegistryModel definitions describe how a registry revision maps declaration PDFs, submitted files, justificantes, and official workbooks into target casillas. The contract records parser identity, accepted artefact kind, match strategy, confidence, coverage, legal grounding, source grounding, and the explicit specimen / round-trip flags that prevent silent provisional extraction.

The schema remains declarative authority only: it does not import parser adapters, read artefacts, or run extraction. Registry validation checks local reference closure and evidence sufficiency before RegistrySnapshot exposes the profiles to application and adapter consumers.

Registry-build validation checks casilla, export-field, legal, and source closure for each profile, together with artefact kind, dotted parser, bbox anchor, specimen, and round-trip conformance for these contracts.

See also

ModeloRevision

Revision record that owns committed extraction-profile rows.

RegistrySnapshot

Validated filing-context view that exposes extraction profiles by id.

CasillaDefinition

Target casilla metadata each extraction target must reference.

LegalReference

Legal evidence rows cited through legal_refs.

SourceReference

Source evidence rows cited through source_refs.

class ExtractionSurface(*values)[source]

Bases: StrEnum

The artefact an extraction profile reads casilla values out of.

BORRADOR_PDF
DECLARACION_PDF
JUSTIFICANTE_PDF
EXPORT_RECORD
OFFICIAL_WORKBOOK
class ExtractionArtefactKind(*values)[source]

Bases: StrEnum

A stored artefact an extraction profile will accept as its input.

Deliberately NOT the same vocabulary as ExtractionSurface, despite the overlap: a surface says what the profile was designed to read, an artefact kind says what a caller may hand it. submitted_file is an artefact and never a surface, and borrador_pdf is a surface with no artefact kind of its own.

SUBMITTED_FILE
DECLARATION_PDF
JUSTIFICANTE_PDF
OFFICIAL_WORKBOOK
class ExtractionMatchStrategy(*values)[source]

Bases: StrEnum

How a target casilla is located on the surface.

NUMERIC_CASILLA
NAMED_LABEL
BBOX_ANCHORED
class ExtractionValueKind(*values)[source]

Bases: StrEnum

What kind of value the extractor expects to read.

AMOUNT
TEXT
ENUM
class BboxValueOffset(*values)[source]

Bases: StrEnum

Where the value sits relative to its anchoring box number.

LEFT_OF_NUMBER
ABOVE_NUMBER
RIGHT_OF_NUMBER
class ExtractionConfidence(*values)[source]

Bases: StrEnum

How far a profile’s output may be trusted without review.

STRICT
REVIEW_REQUIRED
class ExtractionVerificationSource(*values)[source]

Bases: StrEnum

What evidence backs a profile’s extraction accuracy.

NOT_APPLICABLE and HISTORICAL_SUPPRESSION are distinct on purpose: the first says verification does not apply, the second says it was deliberately withheld for a historical revision. Collapsing them would report a suppression as an absence.

REAL_AEAT_CORPUS_PDF
SYNTHETIC_FROM_AEAT_PUBLISHED_TEXT
HISTORICAL_SUPPRESSION
NOT_APPLICABLE
class BboxAnchorSpec(**data)[source]

Bases: RegistryModel

Spatial anchor configuration for the bbox_anchored extraction strategy.

box_number_pattern: str
value_offset: BboxValueOffsetField
anchor_x_min: float | None
anchor_x_max: float | None
value_x_max: float | None
column_anchor: str | None
class ExtractionTargetDefinition(**data)[source]

Bases: RegistryModel

Per-target descriptor for a registry extraction profile.

value_kind is a PARSE DIRECTIVE, not a declaration of the target’s type. It answers only “how is the captured token turned into a value?”, and the parser branches on it exactly one way: amount gets Spanish-decimal parsing, the blank-box guard and the word-level positional pass, while everything else carries the raw token through unchanged.

enum is therefore a documentation refinement of text and makes no enforceable claim about the value space. Nothing in this schema declares the permitted members of any target’s enumeration, so there is no set to validate against and no consumer that would consult one. A reader meeting value_kind = "enum" should read “expected to be one of a closed set, and nothing checks that”, not “constrained”.

The consequence is that value_kind and data_type answer different questions and cannot be compared for coherence. A target declaring enum over a casilla whose data_type is text or integer is not incoherent – the first says how to read the printed token, the second says what the casilla holds. Under this reading such targets are documentation rather than defects, which is why none of them is “corrected” to text.

Measured 2026-07-28 by walking every profile on every revision through the authority, eight targets declare enum and all eight sit over text or integer. Four are on the declaracion_pdf surface and are the ones this ruling was raised against (Modelo 036 decl.event-kind, Modelo 232 decl.tipo-ejercicio in both revisions, Modelo 840 decl.tipo-declaracion). The other four are export_record targets on Modelo 180, and they are if anything a stronger case for the same reading: no consumer reads value_kind on that surface at all.

Making enum load-bearing later is a real option, but it requires declaring the value space first – a member list per target, grounded in AEAT’s published values – because a constraint no one can enumerate cannot be enforced. Until then the parser must treat enum and text identically, which is pinned by adapters.inbound.declaracion.tests.test_extraction_value_kind_contract.

casilla_id: CasillaId
match_strategy: ExtractionMatchStrategyField
value_kind: ExtractionValueKindField
label_pattern: str | None
bbox_anchor: BboxAnchorSpec | None
class ExtractionProfileDefinition(**data)[source]

Bases: RegistryModel

Registry extraction profile for declaration/borrador/workbook artefacts.

id: ExtractionProfileId
surface: ExtractionSurfaceField
artefact_kind: str
accepted_artefact_kinds: tuple[ExtractionArtefactKindField, ...]
parser: str
target_casillas: tuple[ExtractionTargetDefinition, ...]
confidence: ExtractionConfidenceField
provisional_pending_specimen: bool
corpus_round_trip_verified: bool
verification_source: ExtractionVerificationSourceField | None
min_coverage: DecimalValue
failure_semantics: Literal['fail_hard']
legal_refs: LegalRefs
source_refs: SourceRefs