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:
objectRepository over encrypted SQL-backed past-filing observations.
Stores
RegistryModeloObservationrows forresolve_bindings_from_local_store(),resolve_relations_from_local_store(), andevaluate_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 anObservationLayerspayload: 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_NAMESPACEthroughSecureBoundRepository.- Parameters:
bucket_id (str | None)
objects (SecureObjectRepository | None)
settings (Settings | None)
-
sensitivity:
ClassVar[SensitivityClass]¶
- payload_type¶
alias of
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:
- Parameters:
payload (ObservationLayers)
- envelope_identifier(payload)[source]¶
Return the storage key of the coordinate
payloadbelongs to.- Return type:
- Parameters:
payload (ObservationEnvelopePayload)
- load(identifier)[source]¶
Return the effective envelope stored under
identifier.- Return type:
- Parameters:
identifier (str)
- load_observation(modelo, period)[source]¶
Return the effective observation for one single-filer coordinate, or None.
- Return type:
- Parameters:
- load_observation_layers(modelo, period, *, member_nif=None)[source]¶
Return both layers of one coordinate; a coordinate never written has neither.
- Return type:
- 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_nifis an optional grupo-de-entidades member NIF. When supplied, the storage identifier is widened (seemember_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<-322per_grupo_memberaggregation enumerates. WhenNonethe single-filer key is unchanged.stamped_revision_idis 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_metadatais 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_headerscarries the filed fichero’s typed diseño header facts. It is a SEPARATE parameter rather than moresource_metadatakeys because that mapping is assembled from a fixed key set by its producer, so a fact not named there never reaches storage.overriderecords 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_writeand the storage backend’s batch boundary so the pair cannot half-persist.- Return type:
- Parameters:
observation (RegistryModeloObservation)
source_kind (ObservationSourceKind | str)
stamped_revision_id (RevisionId)
captured_at (datetime | None)
member_nif (str | None)
source_headers (tuple[ObservedHeaderFact, ...])
result_disposition (ResultDispositionProjection | None)
prior_domiciliation_election (PriorDomiciliationElectionProjection | None)
override (ObservationOverride | None)
- 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
modelotest 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:
- Parameters:
modelo (str)
- iter_layers()[source]¶
Iterate every stored coordinate’s layers while translating storage failures inward.
- Return type:
- save(payload)[source]¶
Persist one envelope into its layer while translating storage failures inward.
- Return type:
- 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:
- Parameters:
payload (ObservationEnvelopePayload)
expected_revision_id (str | None)
- 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.
- 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:
- Parameters:
modelo (str)
period (Period)
member_nif (str | None)
replacement_official (ObservationEnvelopePayload | None)
- 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 throughIvaWalletDecisionSourceResolver.Latest-state rows use
IVA_WALLET_RECONCILIATION_DECISIONS_NAMESPACE; immutable audit events useIVA_WALLET_RECONCILIATION_DECISION_EVENTS_NAMESPACE. Both storeIvaCompensationReconciliationDecisionpayloads inEnveloperecords throughSecureBoundRepository.- Parameters:
bucket_id (str | None)
objects (SecureObjectRepository | None)
settings (Settings | None)
-
sensitivity:
ClassVar[SensitivityClass]¶
- 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:
- Parameters:
payload (IvaWalletDecisionEnvelopePayload)
- save_decision(decision)[source]¶
Persist
decisionto 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:
- Parameters:
decision (IvaCompensationReconciliationDecision)
- load_decision(taxpayer_nif, target_period)[source]¶
Return the latest persisted
IvaCompensationReconciliationDecisionfor the given period.- Return type:
- Parameters:
- list_decisions()[source]¶
Return the latest persisted IVA wallet decisions in target-period order.
Each element is an
IvaCompensationReconciliationDecisionsorted 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:
- 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:
- Parameters: