#!/usr/bin/env python3 """Bounded-memory stream helpers for the Hermes SCM broker.""" from __future__ import annotations import tempfile import time from typing import BinaryIO from gitea_api_policy import PolicyError def spool_response( response, maximum: int, forbidden: tuple[bytes, ...], *, memory_limit: int, chunk_size: int, deadline_seconds: float, ) -> tuple[BinaryIO, int]: """Spool an upstream response to disk while scanning chunk boundaries.""" spool = tempfile.SpooledTemporaryFile(max_size=memory_limit, dir="/tmp") carry = b"" total = 0 deadline = time.monotonic() + deadline_seconds try: while True: remaining = deadline - time.monotonic() if remaining <= 0: raise PolicyError("SCM upstream response deadline exceeded") raw = getattr(getattr(response, "fp", None), "raw", None) sock = getattr(raw, "_sock", raw) if hasattr(sock, "settimeout"): sock.settimeout(remaining) chunk = response.read(chunk_size) if not chunk: break total += len(chunk) if total > maximum: raise PolicyError("SCM upstream response exceeds the safe size limit") candidate = carry + chunk if any(value in candidate for value in forbidden): raise PolicyError( "Git upstream response contains runtime credential material" ) width = max(len(value) for value in forbidden) - 1 carry = candidate[-width:] if width else b"" spool.write(chunk) spool.seek(0) return spool, total except Exception: spool.close() raise