"""Executable completeness contract for scoped secret references.""" from __future__ import annotations from dataclasses import fields import pytest from aios_v2r1.secret_scope import SecretRef from aios_v2r1.tenant_context import ScopeError, ValidationError def secret(**changes: object) -> SecretRef: values: dict[str, object] = { "secret_id": "channel-key", "tenant_id": "tenant-a", "cell_id": "cell-a", "kind": "channel", "version": "v1", "broker_path": "secret://tenant-a/cell-a/channel-key/v1"} values.update(changes) return SecretRef(**values) # type: ignore[arg-type] @pytest.mark.parametrize("path", [ "secret://tenant-a/cell-a/channel-key/v1", "secret://models/provider/key-v2", "secret://runtime/cell-a/signing_key"]) def test_valid_broker_paths_are_references(path: str) -> None: assert secret(broker_path=path).broker_path == path @pytest.mark.parametrize("path", [ "", "vault://tenant-a/key", "secret://", "secret:///key", "secret://tenant-a/../tenant-b/key", "secret://tenant-a//key", "secret://tenant-a/key?version=1", "secret://tenant-a/key#fragment"]) def test_broker_path_traversal_and_malformed_paths_are_rejected(path: str) -> None: with pytest.raises(ValidationError, match="broker path"): secret(broker_path=path) @pytest.mark.parametrize(("tenant_id", "cell_id", "allowed"), [ ("tenant-a", "cell-a", True), ("tenant-b", "cell-a", False), ("tenant-a", "cell-b", False)]) def test_secret_scope_is_exact(tenant_id: str, cell_id: str, allowed: bool) -> None: assert secret().can_be_used_by(tenant_id=tenant_id, cell_id=cell_id) is allowed @pytest.mark.parametrize("kind", ["channel", "model", "tool", "runtime"]) def test_secret_kind_allowlist(kind: str) -> None: assert secret(kind=kind).kind == kind def test_invalid_secret_kind_is_rejected() -> None: with pytest.raises(ValidationError, match="kind"): secret(kind="admin") @pytest.mark.parametrize("changes", [ {"secret_id": "../key"}, {"secret_id": " key "}, {"version": "../v2"}, {"version": ""}, {"tenant_id": "Tenant-A"}, {"cell_id": "cell/a"}]) def test_secret_identifiers_and_version_are_validated(changes: dict[str, str]) -> None: with pytest.raises(ValidationError): secret(**changes) def test_reference_never_contains_a_secret_value_field() -> None: assert "value" not in {field.name for field in fields(SecretRef)} assert "super-secret-value" not in repr(secret()) def test_broker_resolution_uses_only_the_validated_reference() -> None: seen: list[SecretRef] = [] class Broker: def read_secret(self, reference: SecretRef) -> str: seen.append(reference) return "resolved-value" reference = secret() assert reference.resolve(Broker()) == "resolved-value" assert seen == [reference] @pytest.mark.parametrize("broker", [None, object()]) def test_missing_or_invalid_broker_fails_closed(broker: object | None) -> None: with pytest.raises(ScopeError, match="secret broker unavailable"): secret().resolve(broker) def test_broker_error_is_sanitized_without_secret_leakage() -> None: class BrokenBroker: def read_secret(self, reference: SecretRef) -> str: raise RuntimeError("provider leaked super-secret-value") with pytest.raises(ScopeError, match="secret broker unavailable") as raised: secret().resolve(BrokenBroker()) assert "super-secret-value" not in str(raised.value) assert raised.value.__cause__ is None assert raised.value.__context__ is None