"""Artifact materialization boundaries used by ARR delivery validation.""" from __future__ import annotations import os import shutil from pathlib import Path from typing import Protocol from arr_ingestion.contracts import IngestionError class ArtifactStore(Protocol): def materialize(self, object_key: str, destination: Path, max_bytes: int) -> None: """Copy one immutable object to a new private local file.""" class LocalObjectStore: """Controlled local implementation for tests and offline vertical slices.""" def __init__(self, root: Path) -> None: self._root = root.resolve() if not self._root.is_dir(): raise ValueError("object store root must be an existing directory") def materialize(self, object_key: str, destination: Path, max_bytes: int) -> None: source = self._root.joinpath(*object_key.split("/")) try: resolved = source.resolve(strict=True) resolved.relative_to(self._root) except (FileNotFoundError, OSError, ValueError): raise IngestionError("ARTIFACT_NOT_FOUND", "delivery artifact is unavailable") from None if source.is_symlink() or not resolved.is_file(): raise IngestionError("ARTIFACT_NOT_FOUND", "delivery artifact is unavailable") destination.parent.mkdir(parents=True, exist_ok=True, mode=0o700) descriptor = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) copied = 0 try: with resolved.open("rb") as source_handle, os.fdopen(descriptor, "wb") as target: descriptor = -1 while True: chunk = source_handle.read(1024 * 1024) if not chunk: break copied += len(chunk) if copied > max_bytes: raise IngestionError( "ARTIFACT_TOO_LARGE", "delivery artifact exceeds its size limit" ) target.write(chunk) target.flush() os.fsync(target.fileno()) except Exception: destination.unlink(missing_ok=True) raise finally: if descriptor >= 0: os.close(descriptor) class DirectoryArtifactPublisher: """Small helper for synthetic/local flows; production uses the OSS adapter.""" def __init__(self, root: Path) -> None: self._root = root.resolve() self._root.mkdir(parents=True, exist_ok=True, mode=0o700) def put_file(self, source: Path, object_key: str) -> Path: destination = self._root.joinpath(*object_key.split("/")) try: destination.resolve().relative_to(self._root) except ValueError: raise IngestionError("ARTIFACT_REFERENCE_INVALID", "object key is invalid") from None destination.parent.mkdir(parents=True, exist_ok=True, mode=0o700) if destination.exists(): raise IngestionError("ARTIFACT_CONFLICT", "object key already exists") descriptor = os.open(destination, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) try: with source.open("rb") as source_handle, os.fdopen(descriptor, "wb") as target: descriptor = -1 shutil.copyfileobj(source_handle, target, length=1024 * 1024) target.flush() os.fsync(target.fileno()) except Exception: destination.unlink(missing_ok=True) raise finally: if descriptor >= 0: os.close(descriptor) return destination