"""The registry credential (monky-design-docs doc 24 §4a). The bundle's manifest carries one entry marked `use: registry-auth` — the estate-wide read-only Harbor robot, copied by monky-tenancy into this environment's own prefix so the agent can read it with the OpenBao policy it already has. It is NOT an env var (an entry in `.env` would put the registry password into every container's environment), so it never reaches the compose file: it is written to a Docker config **the agent owns**, and `DOCKER_CONFIG` points the docker CLI at it. That last part is the whole point. The unit runs as `monky-deployd`, whose home is the state dir, so a `docker login` performed by a human or by root is invisible to it — the failure looks exactly like "no credentials at all" (env-dev-01, 2026-09-08). Accepted shapes for the secret's value, because the seeded robot has been written both ways: * a JSON object: `{"registry": …, "username": …, "password": …}` * a `username:password` string, with the registry taken from `registry_host` config """ from __future__ import annotations import base64 import json import logging from dataclasses import dataclass from pathlib import Path log = logging.getLogger("monky-deployd.registry") USE = "registry-auth" class RegistryAuthError(Exception): pass @dataclass class RegistryAuth: registry: str username: str password: str def docker_config(self) -> dict: token = base64.b64encode(f"{self.username}:{self.password}".encode()).decode() return {"auths": {self.registry: {"auth": token}}} def parse(value: str, *, default_registry: str) -> RegistryAuth: """`value` is whatever the KV entry held; never logged, never echoed.""" text = (value or "").strip() if not text: raise RegistryAuthError("empty registry credential") if text.startswith("{"): try: data = json.loads(text) except json.JSONDecodeError as exc: raise RegistryAuthError("registry credential is not valid JSON") from exc user, pw = data.get("username"), data.get("password") registry = data.get("registry") or default_registry if not user or not pw: raise RegistryAuthError("registry credential JSON needs username + password") return RegistryAuth(registry=str(registry), username=str(user), password=str(pw)) if ":" not in text: raise RegistryAuthError("registry credential is neither JSON nor username:password") user, _, pw = text.partition(":") if not default_registry: raise RegistryAuthError("username:password credential needs a configured registry host") return RegistryAuth(registry=default_registry, username=user, password=pw) def write_docker_config(dir_path: Path, auth: RegistryAuth) -> Path: """0600 `config.json` in a directory the agent owns; DOCKER_CONFIG points the CLI at it.""" dir_path = Path(dir_path) dir_path.mkdir(parents=True, exist_ok=True) dir_path.chmod(0o700) target = dir_path / "config.json" tmp = dir_path / "config.json.tmp" tmp.write_text(json.dumps(auth.docker_config(), indent=2) + "\n") tmp.chmod(0o600) tmp.replace(target) log.info("registry credential in place for %s (%s)", auth.registry, auth.username) return target