feat(files): add source-file upload with MinIO storage and Postgres repositories

Why:
- Implements plan 001 Phase 3's upload orchestration.

Changes:
- ObjectStorage port and MinIO adapter, thread-offloaded per ADR-0017.
- Tenant-scoped repositories for api_keys, source_files, ingestion_jobs.
- upload_source_file implementing the two-transaction shape with
  (tenant_id, domain, content_sha256) idempotency.

Impact:
- This phase stores bytes only -- chunks_indexed is always 0 until
  Phase 4/5 add parsing/embedding.
This commit is contained in:
2026-08-19 15:00:27 +03:30
parent e97ce6e5f3
commit c9cf7b368b
19 changed files with 758 additions and 4 deletions

View File

@@ -0,0 +1,25 @@
import uuid
import pytest
from src.application.files.storage_keys import source_file_object_key
pytestmark = pytest.mark.unit
def test_source_file_object_key_is_server_derived_not_filename() -> None:
tenant_id = uuid.uuid4()
source_file_id = uuid.uuid4()
key = source_file_object_key(tenant_id, source_file_id)
assert key == f"tenants/{tenant_id}/source-files/{source_file_id}/original"
def test_source_file_object_key_differs_per_tenant() -> None:
source_file_id = uuid.uuid4()
key_a = source_file_object_key(uuid.uuid4(), source_file_id)
key_b = source_file_object_key(uuid.uuid4(), source_file_id)
assert key_a != key_b