aeat.application.modelo._review_package_recipient_registry module

Recipient fingerprint registry for review-package recipient encryption.

This module lets a taxpayer record who they trust to receive an encrypted review package – an accountant or gestor – by the SHA-256 fingerprint of that recipient’s X25519 public key, verified out-of-band (read aloud, compared over a separate channel) before it is trusted. It is the taxpayer-side companion to _review_package_recipient_encryption, which consumes a registered recipient’s public key to seal a review package so only that recipient’s matching private key can open it.

This registry never stores a private key of any kind: it is exclusively a record of OTHER PEOPLE’s public keys, mirroring how a real address book of trusted correspondents works. The taxpayer’s own encryption keypair (needed only for a future reverse flow, where an accountant encrypts feedback back to the taxpayer) is out of scope for this module.

Persistence follows the exact shape of BienesInversionIvaRegisterRepository: one FINANCIAL-sensitivity secure-object singleton per bucket, an empty register when absent, and duplicate-recipient_id refusal on add.

The encrypted row’s storage policy is governed by SensitivityClass; this registry stores public-key trust records at FINANCIAL sensitivity, never private key material.

See also

_review_package_recipient_encryption

Consumes a registered recipient’s public key to encrypt a review package.

_review_package_signing

Sibling per-profile keypair primitive (Ed25519, signature-only) this module’s X25519 keypair concept deliberately does not share key material with – signing and encryption keys must not be reused across purposes.

BienesInversionIvaRegisterRepository

The structural template this repository mirrors.

exception RecipientFingerprintRegistryError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: AeatError

Base error for recipient-fingerprint registry failures.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]
exception RecipientAlreadyRegisteredError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: RecipientFingerprintRegistryError

Raised when add is called with a recipient_id already on file.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]
exception RecipientNotRegisteredError(message=None, *, context=None, suggestion=None, translated_message=None)[source]

Bases: RecipientFingerprintRegistryError

Raised when remove or a lookup names a recipient_id not on file.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • suggestion (str | None)

  • translated_message (str | None)

Return type:

None

code: ClassVar[ErrorCode]
class RecipientFingerprintRecord(**data)[source]

Bases: BaseModel

One trusted recipient’s public encryption key on file.

public_key_hex is the recipient’s raw 32-byte X25519 public key (RFC 7748), hex-encoded. fingerprint_sha256 is a plain (non- persisted) property – SHA-256 of the raw public key bytes, hex-encoded – so it can never drift from the key it fingerprints and never needs to round-trip through the strict-extra-forbid persistence boundary; it exists purely for a human-readable out-of-band verification string (the taxpayer reads it aloud to / compares it against a value the accountant reads from their own key export).

Parameters:
recipient_id: str
label: str
public_key_hex: str
added_at: datetime
property fingerprint_sha256: str

SHA-256 hex digest of the raw public key bytes, for out-of-band display.

public_key()[source]

Reconstruct the live X25519PublicKey from stored raw bytes.

Return type:

X25519PublicKey

class RecipientFingerprintRegister(**data)[source]

Bases: BaseModel

A bucket’s full set of trusted recipient fingerprint records.

Parameters:

records (tuple[RecipientFingerprintRecord, ...])

records: tuple[RecipientFingerprintRecord, ...]
public_key_hex_from_raw_bytes(raw_public_key)[source]

Validate and hex-encode a raw X25519 public key.

Parameters:

raw_public_key (bytes) – Exactly 32 raw bytes (RFC 7748 encoding).

Raises:

RecipientFingerprintRegistryError – If raw_public_key is not exactly 32 bytes, or is not a well-formed X25519 point.

Return type:

str

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

Bases: object

Governed repository for the encrypted recipient-fingerprint register.

The singleton row is owned by MODELO_REVIEW_PACKAGE_RECIPIENT_FINGERPRINT_REGISTRY_NAMESPACE and persisted through SecureObjectRepository, mirroring BienesInversionIvaRegisterRepository.

Parameters:
load()[source]

Load the register, returning an empty register when absent.

Raises:
  • RecipientFingerprintRegistryError – When the envelope exists but the filesystem I/O itself fails.

  • DecryptionError – When the envelope exists but its ciphertext fails AEAD authentication (tampered or corrupted at rest) – propagated verbatim rather than re-wrapped, so a caller can distinguish “this register was tampered with” from a generic I/O failure. This is the anti- tautology proof this repository’s roundtrip tests require: a corrupted on-disk payload must be refused loudly, not silently coerced into a plausible-looking empty register.

Return type:

RecipientFingerprintRegister

list()[source]

Return every registered recipient record.

Return type:

tuple[RecipientFingerprintRecord, ...]

get(recipient_id)[source]

Return the record for recipient_id.

Raises:

RecipientNotRegisteredError – If no record with that id exists.

Return type:

RecipientFingerprintRecord

Parameters:

recipient_id (str)

add(*, recipient_id, public_key_hex, label='', added_at=None)[source]

Atomically add a recipient record and refuse a duplicate id.

Parameters:
  • recipient_id (str) – Stable operator-chosen label (e.g. "my-accountant"). Must be unique within the register.

  • public_key_hex (str) – The recipient’s raw 32-byte X25519 public key, hex-encoded (see public_key_hex_from_raw_bytes()).

  • label (str) – Optional free-text display name.

  • added_at (datetime | None) – Optional override for the record’s added_at timestamp (tests only); defaults to the current UTC time.

Raises:

RecipientAlreadyRegisteredError – When a record with the same recipient_id already exists.

Return type:

RecipientFingerprintRegister

remove(recipient_id)[source]

Atomically remove the record for recipient_id.

Raises:

RecipientNotRegisteredError – When no record with that id exists.

Return type:

RecipientFingerprintRegister

Parameters:

recipient_id (str)