Model/tests
Jun-te Kim 708f1b5d18 repositories: UserAddressRepository + UserAddressCsvS3Repository (CSV-on-S3 adapter)
Adds the persistence layer for UserAddress batches:

- Abstract UserAddressRepository with load_batch / save_batch.
- Concrete UserAddressCsvS3Repository over CsvS3Client:
  - load_batch reads canonical upload columns (Address 1/2/3, Postcode,
    Internal Reference), comma-joins non-empty address parts, and
    passes Internal Reference through (None when missing/empty).
  - save_batch writes a 3-column CSV (user_address,postcode,
    internal_reference) to {path_prefix}/{ISO datetime}_{uuid8}.csv
    and returns the s3://bucket/key URI.
- Postcode sanitisation flows through UserAddress.__post_init__; the
  repo never calls sanitise_postcode directly.

Tests (moto-backed) cover: three-line address load, Address-1-only
load, missing Internal Reference, save->reload round trip, and
unique-filename-per-save. pyright --strict clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:37:02 +00:00
..
domain postcode_splitter: pure domain (UserAddress, sanitise_postcode, postcode_batching) 2026-05-19 16:45:47 +00:00
infrastructure infrastructure: typed S3/SQS clients (S3Client, CsvS3Client, SqsClient, Address2UprnQueueClient) 2026-05-19 17:12:21 +00:00
orchestration orchestration: add TaskOrchestrator.create_child_subtask primitive 2026-05-19 17:19:41 +00:00
repositories repositories: UserAddressRepository + UserAddressCsvS3Repository (CSV-on-S3 adapter) 2026-05-19 17:37:02 +00:00
utilities utilities/aws_lambda: @subtask_handler injects TaskOrchestrator as third positional arg 2026-05-19 17:31:27 +00:00
__init__.py added postcode splitter rewrite to ddd 2026-05-19 16:35:09 +00:00