cadrumo.adapters.persistence.profile.calculation_observations module

Encrypted persistence adapters for calculation observations and IVA wallet decisions.

The application owns payloads, key derivation, validation, and capability contracts. This module binds those contracts to encrypted secure-object storage.

Core types: SensitivityClass, SecureObjectRepository.

class CalculationObservationRepository(*, bucket_id=None, objects=None, settings=None)[source]

Bases: object

Repository over encrypted SQL-backed past-filing observations.

Stores RegistryModeloObservation rows for resolve_bindings_from_local_store(), resolve_relations_from_local_store(), and evaluate_cross_period_clean_state(). It owns encrypted value history only; filing-grade source proof is assembled by the clean-state service from this repository plus filing, verification, and justificante repositories.

Each (modelo, filing_year, period[, member]) coordinate is one row holding an ObservationLayers payload: the official layer observed from AEAT and the pending-local layer written by local filings and operator figures. A write replaces only the layer its source kind selects, so a local figure never destroys captured AEAT evidence. Envelope reads return the effective layer, the pending-local one when present.

Rows are bound to CALCULATION_OBSERVATIONS_NAMESPACE through SecureBoundRepository.

Parameters:
namespace: ClassVar[str]
sensitivity: ClassVar[SensitivityClass]
schema_version: ClassVar[int]
payload_type

alias of ObservationLayers

classmethod payload_model()[source]

Return the stored row payload model.

Return type:

type[ObservationLayers]

property secure_object_repository: SecureObjectRepository

Return the concrete secure-object backend shared by co-committed writes.

extract_identifier(payload)[source]

Return the storage key of one stored layer row.

Return type:

str

Parameters:

payload (ObservationLayers)

envelope_identifier(payload)[source]

Return the storage key of the coordinate payload belongs to.

Return type:

str

Parameters:

payload (ObservationEnvelopePayload)

load(identifier)[source]

Return the effective envelope stored under identifier.

Return type:

ObservationEnvelopePayload | None

Parameters:

identifier (str)

load_observation(modelo, period)[source]

Return the effective observation for one single-filer coordinate, or None.

Return type:

ObservationEnvelopePayload | None

Parameters:
load_observation_layers(modelo, period, *, member_nif=None)[source]

Return both layers of one coordinate; a coordinate never written has neither.

Return type:

ObservationLayers

Parameters:
prepare_observation_envelope(observation, *, source_kind, stamped_revision_id, captured_at=None, member_nif=None, source_metadata=None, source_headers=(), result_disposition=None, prior_domiciliation_election=None, override=None)[source]

Build one validated observation envelope without writing it.

Every writer traverses this method, so the registry and Modelo 303 carry checks below run before any write is prepared.

member_nif is an optional grupo-de-entidades member NIF. When supplied, the storage identifier is widened (see member_observation_key()) so distinct members’ filings for the same (modelo, filing_year, period) persist as separate rows instead of overwriting — the cross-member fan-in the 353<-322 per_grupo_member aggregation enumerates. When None the single-filer key is unchanged.

stamped_revision_id is the required registry revision id the source filing resolved to at capture time. There is no inferred or legacy fallback: every producer must pass its authoritative coordinate, which this boundary checks against the law-determined revision.

source_metadata is source-specific encrypted provenance. It is never part of repository keys and must only contain data that belongs inside the AUDIT-class secure payload; live AEAT captures use it for register status, expediente identity, and authenticated taxpayer/member identity consumed by the cross-period clean-state proof.

source_headers carries the filed fichero’s typed diseño header facts. It is a SEPARATE parameter rather than more source_metadata keys because that mapping is assembled from a fixed key set by its producer, so a fact not named there never reaches storage.

override records the audit of an operator figure; only a non-official envelope can carry one.

Every Modelo 303 envelope crosses the canonical disposition-aware normalization ingress. Incomplete or conflicting evidence is refused; there is no generic unnormalized storage shape. Callers that co-emit this envelope with a history projection use to_secure_object_write and the storage backend’s batch boundary so the pair cannot half-persist.

Return type:

ObservationEnvelopePayload

Parameters:
iter_modelo(modelo)[source]

Yield the effective observation of every stored coordinate of modelo.

Used by grouped previous-filing and clean-state readers to enumerate all known source rows for a modelo, including member-widened keys.

The base scan verifies each row’s key before yielding it, which this filter depends on: the modelo test below reads the payload’s own coordinates, so a row filed under another key would enter the window it describes rather than the one it is stored in. The verified scan recomputes the natural key from each payload and refuses a mismatch instead of yielding it.

Return type:

Iterator[ObservationEnvelopePayload]

Parameters:

modelo (str)

iter_layers()[source]

Iterate every stored coordinate’s layers while translating storage failures inward.

Return type:

Iterator[ObservationLayers]

iter_records()[source]

Iterate the effective envelope of every stored coordinate.

Return type:

Iterator[ObservationEnvelopePayload]

save(payload)[source]

Persist one envelope into its layer while translating storage failures inward.

Return type:

None

Parameters:

payload (ObservationEnvelopePayload)

to_secure_object_write(payload, *, expected_revision_id=None)[source]

Prepare the write placing one envelope into its layer, for an outer transaction.

Return type:

SecureObjectWrite

Parameters:
promote_pending_local(modelo, period, *, member_nif=None, source_kind, source_metadata, captured_at)[source]

Prepare the write that makes the pending-local layer the official one.

An operator override is not AEAT’s answer, so a pending layer carrying one is left in place and nothing is written.

Return type:

tuple[SecureObjectWrite, ...]

Parameters:
clear_pending_local(modelo, period, *, member_nif=None, replacement_official=None)[source]

Prepare the write that removes the pending-local layer, optionally replacing the official one.

Return type:

tuple[SecureObjectWrite, ...]

Parameters:
class IvaWalletDecisionRepository(*, bucket_id=None, objects=None, settings=None)[source]

Bases: SecureBoundRepository[IvaWalletDecisionEnvelopePayload]

Repository over encrypted SQL-backed IVA wallet reconciliation decisions.

Holds one latest decision per (taxpayer_nif, target_year, target_period) triple for calculation lookup, and also writes every distinct decision to an immutable audit-event namespace. Decisions are AUDIT-class — they record the resolved gap between a taxpayer’s local IVA compensation recurrence and the live AEAT wallet, which downstream calculation chains consult through IvaWalletDecisionSourceResolver.

Latest-state rows use IVA_WALLET_RECONCILIATION_DECISIONS_NAMESPACE; immutable audit events use IVA_WALLET_RECONCILIATION_DECISION_EVENTS_NAMESPACE. Both store IvaCompensationReconciliationDecision payloads in Envelope records through SecureBoundRepository.

Parameters:
namespace: ClassVar[str]
history_namespace: ClassVar[str]
sensitivity: ClassVar[SensitivityClass]
schema_version: ClassVar[int]
history_schema_version: ClassVar[int]
payload_type

alias of IvaWalletDecisionEnvelopePayload

extract_identifier(payload)[source]

Return the natural id for payload (used as the SQL object key).

Subclasses MUST override. The base implementation raises NotImplementedError.

Return type:

str

Parameters:

payload (IvaWalletDecisionEnvelopePayload)

save_decision(decision)[source]

Persist decision to latest lookup and immutable audit history.

Both rows commit in ONE transaction. Writing the latest state and then appending the audit event as a second, independent write left a window in which a failure between them persisted a decision the immutable history has no record of – the history exists precisely to explain how the latest state was reached, so a latest row with no event is a decision that cannot be audited. The substrate already owns the transaction boundary; this composes both writes into it.

Return type:

None

Parameters:

decision (IvaCompensationReconciliationDecision)

load_decision(taxpayer_nif, target_period)[source]

Return the latest persisted IvaCompensationReconciliationDecision for the given period.

Return type:

IvaCompensationReconciliationDecision | None

Parameters:
list_decisions()[source]

Return the latest persisted IVA wallet decisions in target-period order.

Each element is an IvaCompensationReconciliationDecision sorted by (target_year, target_period, taxpayer_nif, decided_at).

The base scan verifies each row’s key before yielding it, which this listing depends on. The latest-decision key is a hash of the taxpayer and target period, so a decision filed under another taxpayer’s or period’s key is invisible to any check that reads the decrypted decision alone; it would then sort into this list as that other subject’s latest decision and enter reconciliation. The verified scan recomputes the hashed key from each payload and refuses a mismatch.

Return type:

tuple[IvaCompensationReconciliationDecision, ...]

load_decision_history(taxpayer_nif, target_period)[source]

Return decision history for one taxpayer and target period.

Returns an immutable tuple of IvaCompensationReconciliationDecision.

Return type:

tuple[IvaCompensationReconciliationDecision, ...]

Parameters: