Source code for cadrumo.domain.modelos.protocols

"""Domain-level repository Protocols for the modelos aggregate.

Application-layer code that persists or loads modelo work-unit catalogues,
filing records, calculation results, or verification reports depends on these
Protocols, not on the concrete adapter-backed repository classes. This keeps
the domain layer free of adapter imports while still providing typed port surfaces.

The calculation-revision, filing-record, and verification-report protocols
return :class:`CalculationRevisionCatalogue`, :class:`ModeloRecordCatalogue`,
and :class:`VerificationReportCatalogue` instances while keeping application
code independent of concrete storage adapters. The work-unit port is defined
directly in :mod:`~domain.modelos.work_unit_repository`.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, runtime_checkable

if TYPE_CHECKING:
    from collections.abc import Callable

    # pragma: no cover - typing-only boundary DTO (lives in core, not adapters)
    from ...core.secure_object_write import SecureObjectWrite
    from .calculation_revision import CalculationRevisionCatalogue
    from .filing_record import ModeloRecordCatalogue
    from .participation_index import TransactionRevisionParticipationIndex
    from .verification_report import VerificationReportCatalogue


[docs] @runtime_checkable class CalculationRevisionCatalogueRepositoryProtocol(Protocol): """Narrow domain-facing repository contract for calculation revisions. Any object that provides ``exists``, ``load``, and ``save`` over a per-bucket :class:`CalculationRevisionCatalogue` satisfies this protocol. The concrete secure-object-backed implementation is :class:`CalculationRevisionCatalogueRepository`. """ @property def bucket_id(self) -> str | None: """Return the profile bucket id when this repository resolved one.""" ...
[docs] def exists(self) -> bool: """Return whether a calculation-revision catalogue object has been persisted.""" ...
[docs] def load(self) -> CalculationRevisionCatalogue: """Return the persisted catalogue or an empty catalogue if absent. Returns: The :class:`CalculationRevisionCatalogue` loaded from storage. """ ...
[docs] def load_revisioned(self) -> tuple[CalculationRevisionCatalogue, str]: """Return the catalogue together with its current persistence revision. Co-commit callers must carry this revision into their guarded write so rebuilding the singleton catalogue cannot overwrite a concurrent calculation revision. """ ...
[docs] def save(self, catalogue: CalculationRevisionCatalogue) -> None: """Persist ``catalogue`` as the encrypted singleton object.""" ...
[docs] def to_secure_object_write( self, catalogue: CalculationRevisionCatalogue, *, expected_revision_id: str | None = None, ) -> SecureObjectWrite: """Return the :class:`SecureObjectWrite` for ``catalogue`` without committing it. ``expected_revision_id`` is the compare-and-swap half. These catalogues are SINGLETON rows, so a co-commit composed from an unguarded read writes the whole row back and discards any entry another caller added in between. It is declared HERE, not only on the concrete repository, because a caller typed against this protocol could otherwise not pass it at all -- the guard existed and was unreachable. """ ...
[docs] def save_with_secure_object_writes( self, catalogue: CalculationRevisionCatalogue, extra_writes: tuple[SecureObjectWrite, ...], *, expected_revision_id: str | None = None, ) -> None: """Persist ``catalogue`` plus co-emitted secure-object writes atomically.""" ...
[docs] @runtime_checkable class ModeloRecordCatalogueRepositoryProtocol(Protocol): """Narrow domain-facing repository contract for modelo filing records. Any object that provides ``exists``, ``load``, and ``save`` over a per-bucket :class:`ModeloRecordCatalogue` satisfies this protocol. The concrete secure-object-backed implementation is :class:`ModeloRecordCatalogueRepository`. The loaded catalogue supports member-scoped ``current_for`` and ``history_for`` lookups for grupo fan-in filings. """ @property def bucket_id(self) -> str | None: """Return the profile bucket id when this repository resolved one.""" ...
[docs] def exists(self) -> bool: """Return whether a modelo-record catalogue object has been persisted.""" ...
[docs] def load(self) -> ModeloRecordCatalogue: """Return the persisted :class:`ModeloRecordCatalogue` or an empty catalogue if absent.""" ...
[docs] def load_revisioned(self) -> tuple[ModeloRecordCatalogue, str]: """Return the catalogue and secure-object revision for guarded co-commit.""" ...
[docs] def save(self, catalogue: ModeloRecordCatalogue) -> None: """Persist ``catalogue`` as the encrypted singleton object.""" ...
[docs] def mutate(self, mutation: Callable[[ModeloRecordCatalogue], ModeloRecordCatalogue]) -> ModeloRecordCatalogue: """Apply ``mutation`` to the stored catalogue as one revision-guarded unit of work. On the port because the application needs it: the catalogue is a singleton row, so stamping one record rewrites every other, and doing that through ``save`` discards whatever a concurrent caller wrote. """ ...
[docs] def to_secure_object_write( self, catalogue: ModeloRecordCatalogue, *, expected_revision_id: str | None = None, ) -> SecureObjectWrite: """Return the :class:`SecureObjectWrite` for ``catalogue`` without committing it. ``expected_revision_id`` is the compare-and-swap half. These catalogues are SINGLETON rows, so a co-commit composed from an unguarded read writes the whole row back and discards any entry another caller added in between. It is declared HERE, not only on the concrete repository, because a caller typed against this protocol could otherwise not pass it at all -- the guard existed and was unreachable. """ ...
[docs] def save_with_secure_object_writes( self, catalogue: ModeloRecordCatalogue, extra_writes: tuple[SecureObjectWrite, ...], *, expected_revision_id: str | None = None, ) -> None: """Persist ``catalogue`` plus co-emitted secure-object writes atomically.""" ...
[docs] @runtime_checkable class VerificationReportCatalogueRepositoryProtocol(Protocol): """Narrow domain-facing repository contract for verification reports. Any object that provides ``exists``, ``load``, and ``save`` over a per-bucket :class:`VerificationReportCatalogue` satisfies this protocol. The concrete secure-object-backed implementation is :class:`VerificationReportCatalogueRepository`. """ @property def bucket_id(self) -> str | None: """Return the profile bucket id when this repository resolved one.""" ...
[docs] def exists(self) -> bool: """Return whether a verification-report catalogue object has been persisted.""" ...
[docs] def load(self) -> VerificationReportCatalogue: """Return the persisted catalogue or an empty catalogue if absent. Returns: The :class:`VerificationReportCatalogue` loaded from storage. """ ...
[docs] def save(self, catalogue: VerificationReportCatalogue) -> None: """Persist ``catalogue`` as the encrypted singleton object.""" ...
[docs] @runtime_checkable class TransactionParticipationIndexRepositoryProtocol(Protocol): """Narrow domain-facing repository contract for the participation index. The participation index is a per-transaction, derived-and-rebuildable read-side cache mapping a ledger transaction to the calculation revisions it participates in. Unlike the singleton catalogue repositories, its objects are keyed by ``transaction_id``. Any object that provides ``exists``, ``load``, and ``save`` over a :class:`TransactionRevisionParticipationIndex` satisfies this protocol; the concrete secure-object-backed implementation is :class:`TransactionParticipationIndexRepository`. Lifecycle correctness never depends on this cache's freshness — it is rebuilt from the revision catalogue — so the port is a navigation/read seam, not a source of truth. """ @property def bucket_id(self) -> str | None: """Return the profile bucket id when this repository resolved one.""" ...
[docs] def exists(self, transaction_id: str) -> bool: """Return whether a participation-index object exists for ``transaction_id``.""" ...
[docs] def load(self, transaction_id: str) -> TransactionRevisionParticipationIndex: """Return the persisted index for ``transaction_id`` or an empty index if absent.""" ...
[docs] def save(self, index: TransactionRevisionParticipationIndex) -> None: """Persist ``index`` as the encrypted per-transaction object.""" ...
[docs] def to_secure_object_write(self, index: TransactionRevisionParticipationIndex) -> SecureObjectWrite: """Return the secure-object upsert for ``index`` without committing it.""" ...
__all__ = [ "CalculationRevisionCatalogueRepositoryProtocol", "ModeloRecordCatalogueRepositoryProtocol", "TransactionParticipationIndexRepositoryProtocol", "VerificationReportCatalogueRepositoryProtocol", ]