aeat.adapters.persistence.storage.envelope._repository_test_suite module¶
Shared contract test suite for SecureBoundRepository subclasses.
The 8 concrete secure-storage repositories (filing drafts, submissions, filing history, complementaria, justificantes, observations, assets, inventory and friends) each ship a near-identical block of pytest functions that exercise the same anti-tautology / anti-regression properties of the encrypted persistence boundary:
test_round_trip_preserves_payload- save -> load equality across theEnvelopeboundary.test_save_is_idempotent- repeated save does not duplicate rows.test_load_returns_none_when_absent.test_delete_removes/test_delete_removes_object.test_delete_missing_returns_false.test_object_marker_identifies_secure_backend- logical store_dir pointer carries the namespace marker so diagnostic CLI emits stay honest about the backend.test_unsafe_id_rejected- the path-safety gate refuses filesystem-traversal identifiers.test_database_payload_is_encrypted_audit_data- the raw on-disk SQLite file does not surface plaintext that the payload contained.test_foreign_class_object_refused- a row written at the wrongSensitivityClassraisesClassificationErroron load.test_boundary_catches_simulated_field_drop_via_corrupted_payload- the strict-equality witness used by every roundtrip is honest: mutating the on-disk JSON envelope to drop a typed field surfaces either asValidationErroror strict inequality.
This module captures the 11 canonical checks behind one
assert_secure_repository_contract() function. The contract runs
each check against a real SQLite-backed
SecureObjectRepository wired through the
SecureBoundRepository under test. Mocks are forbidden by the
roundtrip discipline; the suite uses
EphemeralMasterKeyProvider and a real
create_engine_from_settings() engine.
The contract function returns the number of checks executed so the caller’s self-test can assert the expected count and prove no check was silently skipped.
- class SecureRepositoryContractCase(repository_factory, first_payload, second_payload, plaintext_witnesses, mutation_field)[source]¶
Bases:
GenericInputs required to run the contract against a concrete repository.
The contract is parameterised by:
repository_factory- zero-arg callable returning a freshSecureBoundRepository[T]instance. Invoked repeatedly so cross-instance roundtrips are exercised. The factory MUST route its underlyingSecureObjectRepositoryat the currently-active process-default engine (i.e. constructConcrete()rather than passing an explicit engine), because the contract harness rebindsAEAT_DATABASE_URLto a fresh SQLite file per check and disposes cached engines between checks.first_payload/second_payload- two distinct, fully-populated payload instances whose extracted identifiers differ. Both must use non-default values for every optional field so the strict-equality witness has signal.plaintext_witnesses- a tuple of byte strings that the contract asserts MUST NOT appear in the raw on-disk SQLite file after the first payload is persisted. Callers supply tax identifiers, monetary amounts, or other plaintext that the payload encodes; the contract simply checks absence.mutation_field- the JSON key insidepayload(the inner object that the envelope wraps) whose deletion should produce either aValidationErroron reload or a strictly unequal payload. The field MUST be required by the payload schema or carry a non-default value infirst_payloadso that the negative case is observable.
- Parameters:
-
repository_factory:
Callable[[],SecureBoundRepository[TypeVar(T, bound=BaseModel)]]¶
- assert_secure_repository_contract(case, *, tmp_path)[source]¶
Run all 11 canonical contract checks against
case.For each check the function:
Disposes any cached process-default engine.
Rebinds
AEAT_DATABASE_URLandAEAT_LOCAL_STORAGE_ROOTthroughoverride_settingsto a fresh SQLite file undertmp_path.Builds a real engine for that URL and materialises the ORM schema.
Activates a real
EphemeralMasterKeyProvider.Invokes the check, which constructs the repository via
case.repository_factory; the repository’s internalSecureObjectRepositorylookup resolves to the engine activated above.Disposes the engine.
Returns the number of checks executed. Callers SHOULD assert this count equals
EXPECTED_CHECK_COUNTso a silently-skipped check is visible at the self-test boundary.- Return type:
- Parameters:
case (SecureRepositoryContractCase)
tmp_path (Path)
- EXPECTED_CHECK_COUNT: int¶
The number of canonical contract checks executed by
assert_secure_repository_contract().The 11 canonical anti-tautology tests reduce to 10 distinct check callables (
test_delete_removesandtest_delete_removes_objectshare an implementation; the contract honours both names but the underlying behaviour runs once per invocation). Plus the raw-bytes inspection (test_database_payload_is_encrypted_audit_data) and the field-drop simulation (test_boundary_catches_simulated_field_drop_via_corrupted_payload) that need the database path / engine handle directly.Total:
len(_PARAM_CHECKS) + 2.