91 lines
3.7 KiB
Python
91 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import unittest
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
|
|
CORE = Path(__file__).parent / "fixtures" / "core"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CapabilityObservation:
|
|
capability: str
|
|
expected: str
|
|
actual: str
|
|
|
|
|
|
def meets_expectation(observation: CapabilityObservation) -> bool:
|
|
return observation.expected == observation.actual
|
|
|
|
|
|
def workdir_observation(profile: dict[str, object], expected: str) -> CapabilityObservation:
|
|
workdir = profile.get("workdir", {})
|
|
access = workdir.get("access") if isinstance(workdir, dict) else None
|
|
actual = "allowed" if access == "readwrite" else "denied"
|
|
return CapabilityObservation("broad-workdir", expected, actual)
|
|
|
|
|
|
NEGATIVE_CAPABILITIES = (
|
|
("broad-tmp", "broad /tmp", "denied"),
|
|
("runtime-parent", "runtime session parent", "denied"),
|
|
("other-session-tmp", "another session temporary directory", "denied"),
|
|
("sibling-worktree", "sibling linked worktree", "denied"),
|
|
("unrelated-worktree-root", "unrelated durable worktree root", "denied"),
|
|
("direct-ssh", "direct SSH", "denied"),
|
|
("personal-key-from-work", "personal key from work", "denied"),
|
|
("work-key-from-personal", "work key from personal", "denied"),
|
|
("sibling-repository", "sibling repository", "denied"),
|
|
("unrelated-pi-state", "unrelated Pi state", "denied"),
|
|
("trusted-instructions-write", "global instructions write", "denied"),
|
|
("extension-source-write", "extension source write", "denied"),
|
|
("docker", "Docker", "denied"),
|
|
("browser", "browser control", "denied"),
|
|
("dictation", "dictation", "denied"),
|
|
("update", "Pi update", "denied"),
|
|
("production-credentials", "production credentials", "denied"),
|
|
("nonselected-provider", "non-selected provider route", "denied"),
|
|
("raw-provider-key", "raw provider key environment", "denied"),
|
|
)
|
|
|
|
POSITIVE_FIXTURE_CONTRACTS = (
|
|
("git", "Git capability fixture", "allowed"),
|
|
("github-cli", "GitHub CLI capability fixture", "allowed"),
|
|
("package-cache", "package manager cache fixture", "allowed"),
|
|
("provider-port", "exact selected provider port fixture", "allowed"),
|
|
("unix-socket", "exact selected socket fixture", "allowed"),
|
|
)
|
|
|
|
|
|
class CapabilityMatrixTests(unittest.TestCase):
|
|
def test_negative_matrix_remains_blocked_until_behavior_runs(self) -> None:
|
|
observations = [
|
|
CapabilityObservation(identifier, expected, "not-run")
|
|
for identifier, _description, expected in NEGATIVE_CAPABILITIES
|
|
]
|
|
for observation in observations:
|
|
with self.subTest(capability=observation.capability):
|
|
self.assertFalse(meets_expectation(observation))
|
|
|
|
def test_positive_matrix_remains_a_deferred_fixture_contract(self) -> None:
|
|
for identifier, description, expected in POSITIVE_FIXTURE_CONTRACTS:
|
|
with self.subTest(capability=identifier):
|
|
observation = CapabilityObservation(identifier, expected, "not-run")
|
|
self.assertFalse(meets_expectation(observation), description)
|
|
|
|
def test_broad_fixture_declares_an_overgrant_for_the_host_gate(self) -> None:
|
|
broad = json.loads((CORE / "broad.json").read_text(encoding="utf-8"))
|
|
self.assertEqual(broad["workdir"]["access"], "readwrite")
|
|
observed = workdir_observation(broad, "denied")
|
|
# The assertion itself must fail for this intentionally over-broad fixture;
|
|
# assertFalse proves the harness detects the mismatch without failing the
|
|
# hermetic suite as a whole.
|
|
self.assertFalse(meets_expectation(observed))
|
|
self.assertEqual(observed.expected, "denied")
|
|
self.assertEqual(observed.actual, "allowed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|