cadrumo.adapters.persistence.profile.invoices module¶
Governed-persistence repository for the invoice catalogue.
InvoiceCatalogueRepository is the sanctioned read/write path for the
InvoiceCatalogue. It stores the catalogue as an
encrypted byte object via
SecureObjectRepository at
FINANCIAL SensitivityClass using
an Envelope wrapper; no plaintext
invoice row, JSON catalogue, or envelope file lands on disk. The
Envelope-wrapping mechanic itself is owned by
ProfileEnvelopedModelSecurePersistence
(_secure_enveloped_document.py); this class retains only the invoice
bucket-ownership guard, which the shared kernel has no domain knowledge of.
This concrete repository is the persistence adapter behind the read-side
InvoiceCatalogueRepositoryProtocol. It lives in
the persistence adapter (not in domain.invoices) because its
secure-object coupling is SQL/crypto-bound; the domain package owns only the
typed InvoiceCatalogue model, its narrow port,
and the InvoicePersistenceError boundary error.
- class InvoiceCatalogueRepository(*, bucket_id=None, objects=None)[source]¶
Bases:
objectRepository over encrypted SQL-backed
InvoiceCataloguestorage.adapters.persistence.storage.secure_object_namespaces.INVOICE_CATALOGUE_NAMESPACEis the central profile-local namespace, schema-version, sensitivity, and singleton-key contract for the encrypted invoice catalogue row. TheInvoiceCataloguepayload is wrapped inEnvelopebeforeSecureObjectRepositorypersists it, andto_secure_object_write()exposes the same write for transaction/event co-commit paths. This class exposes the concrete load/save implementation behindInvoiceCatalogueRepositoryProtocol, composingProfileEnvelopedModelSecurePersistencefor the shared envelope/exists/load/save mechanic and retaining only the invoice-specific bucket-ownership guard.- Parameters:
bucket_id (str | None)
objects (SecureObjectRepository | None)
- load()[source]¶
Return the persisted catalogue or an empty catalogue if absent.
- Return type:
- Returns:
The deserialised
InvoiceCatalogue, or a fresh empty instance when no database object is present.- Raises:
ClassificationError – If the persisted object’s classification is not the sensitivity
INVOICE_CATALOGUE_NAMESPACEdeclares.EnvelopeVersionError – If the envelope schema version is higher than the consumer supports.
- save(catalogue)[source]¶
Persist
catalogueatomically under the file lock.The on-disk database value is an encrypted
EnvelopeBLOB at theSensitivityClassFINANCIALclassification declared byadapters.persistence.storage.secure_object_namespaces.INVOICE_CATALOGUE_NAMESPACE. No plaintext invoice row lands on disk.- Parameters:
catalogue (
InvoiceCatalogue) – TheInvoiceCatalogueto persist.- Return type:
- mutate(mutation)[source]¶
Apply
mutationto the stored catalogue as one guarded unit of work.The catalogue is a SINGLETON row, so adding one invoice is really read-whole-catalogue, rebuild, write whole catalogue. Two operators adding DIFFERENT invoices at once both read the same catalogue and the later write discards the earlier invoice – silently, because the duplicate-identity check never sees the other invoice. A dropped invoice under-declares, which is the failure this repository exists to make impossible.
The bucket-ownership guard runs on the mutation’s OWN result rather than once before it, so a mutation that introduces a foreign invoice is refused on every attempt instead of only the first.
- Parameters:
mutation (
Callable[[InvoiceCatalogue],InvoiceCatalogue]) – Builds the next catalogue from the current one. Raising refuses the whole mutation, unretried.- Return type:
- Returns:
The catalogue as written.
Core types:
InvoiceCatalogue.
- load_revisioned()[source]¶
Return the catalogue and the revision id it was read at.
The read a guarded co-commit needs. Linking and reconciliation both write this catalogue inside a batch with the transaction store, so neither can use the self-committing
mutate(); without the revision the batch rewrites the whole singleton row and drops an invoice another caller added in between.- Return type:
- load_revision()[source]¶
Return the catalogue’s stored revision without decrypting it.
The absent catalogue has the absent-object revision, the same one
load_revisioned()reports for it.Nonemeans the stored row predates recorded revisions, and a caller must treat it as changed.
- to_secure_object_write(catalogue, *, expected_revision_id=None)[source]¶
Return the secure-object upsert for
cataloguewithout committing it.The returned
SecureObjectWritecarries the sameEnvelopeandSensitivityClassclassification thatsave()would persist directly.- Parameters:
catalogue (
InvoiceCatalogue) – TheInvoiceCatalogueto serialise.expected_revision_id (
str|None) – The revisionload_revisioned()reported for the catalogue this one was derived from. This is a SINGLETON row, so without it the write lands over any invoice another caller committed since the read, and a dropped invoice under-declares.
- Return type: