opencode-config/tests/test_check_permissions.py
Sergey 6005c88203
feat: migrate src/ second-brain + tests + python tooling (#17)
* feat(src): migrate second-brain RAG CLI + tests

* fix(embedder): strip hardcoded ai.slaid098.dev endpoint

* refactor: rename slaid098/opencode to opencode-config

* docs(handoff): add pr-5 handoff + ADR-001

* fix(docs): rebase handoff/ADR naming to PR number + drop dangling ADR-009 refs

* fix(tests): update script paths + assertions for opencode-config migration

* fix(pyproject): update cov + ruff paths config/scripts -> .opencode/scripts

* docs: update project map + handoff + ADR

---------

Co-authored-by: opencode-agent <agent@slaid098.dev>
2026-07-23 23:17:18 +03:00

152 lines
5.4 KiB
Python

"""Tests for .opencode/scripts/check-permissions.py — dangerous permission rules guard.
Covers the ``DANGEROUS_PATTERNS`` guard: clean configs pass, ``gh pr checks*``
in agent frontmatter or in ``opencode.json`` triggers a violation with the
ADR-005 reference.
Strategy:
- ``test_clean_configs_pass`` runs the script as a subprocess on the real
(clean) repo configs — black-box, returncode 0, OK message in stdout.
- ``test_gh_pr_checks_in_agent_violation`` writes a temporary agent .md file
into a temp ``AGENTS_DIR`` and points the script at it via monkeypatch, then
calls ``main`` in-process and captures stdout/stderr.
- ``test_gh_pr_checks_in_opencode_json_violation`` mocks
``parse_global_bash_rules`` to return a rule containing ``gh pr checks*``
and asserts ``check_rules`` flags it with the ADR-005 reference.
- ``test_gh_pr_view_statuscheckrollup_violation`` does the same for the
narrower ``gh pr view *--json statusCheckRollup*`` pattern.
"""
import importlib.util
import subprocess
import sys
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parent.parent
SCRIPT_PATH = REPO_ROOT / ".opencode" / "scripts" / "check-permissions.py"
def _load_script():
spec = importlib.util.spec_from_file_location("check_permissions", SCRIPT_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules["check_permissions"] = module
spec.loader.exec_module(module)
return module
cp = _load_script()
# ── clean configs (subprocess black-box) ────────────────────────────────────
def test_clean_configs_pass():
"""On current (clean) repo configs the script exits 0 with OK message."""
result = subprocess.run(
["python3", str(SCRIPT_PATH)],
capture_output=True,
text=True,
check=False,
)
assert result.returncode == 0, result.stderr
assert "OK: No dangerous permission rules found." in result.stdout
# ── gh pr checks in agent frontmatter (in-process, tmp AGENTS_DIR) ──────────
def test_gh_pr_checks_in_agent_violation(tmp_path, monkeypatch, capsys):
"""A temp agent .md with ``"gh pr checks*": allow`` → exit 1 + ADR-005."""
agents_dir = tmp_path / "agents"
agents_dir.mkdir()
agent_file = agents_dir / "test-agent.md"
agent_file.write_text(
"---\n"
"description: test agent with dangerous rule\n"
"mode: subagent\n"
"permission:\n"
" bash:\n"
' "*": deny\n'
' "gh pr checks*": allow\n'
"---\n\n"
"# test agent\n"
)
monkeypatch.setattr(cp, "AGENTS_DIR", agents_dir)
monkeypatch.setattr(cp, "OPENCODE_JSON", tmp_path / "missing-opencode.json")
with pytest.raises(SystemExit) as exc_info:
cp.main()
assert exc_info.value.code == 1
captured = capsys.readouterr()
assert "gh pr checks" in captured.out
assert "ADR-005" in captured.out
assert "Checks API" in captured.out
# ── gh pr checks in opencode.json (mock parse_global_bash_rules) ────────────
def test_gh_pr_checks_in_opencode_json_violation(monkeypatch):
"""Mock parse_global_bash_rules returns gh pr checks* → check_rules flags it."""
fake_rules = {"gh pr checks*": "allow"}
monkeypatch.setattr(cp, "parse_global_bash_rules", lambda _path: fake_rules)
violations = cp.check_rules(fake_rules, "opencode.json")
assert len(violations) == 1
v = violations[0]
assert "gh pr checks" in v
assert "ADR-005" in v
assert "Checks API" in v
# ── gh pr view --json statusCheckRollup (mock parse_global_bash_rules) ──────
def test_gh_pr_view_statuscheckrollup_violation():
"""The narrower statusCheckRollup pattern is also flagged with ADR-005."""
fake_rules = {"gh pr view *--json statusCheckRollup*": "allow"}
violations = cp.check_rules(fake_rules, "opencode.json")
assert len(violations) == 1
v = violations[0]
assert "statusCheckRollup" in v
assert "ADR-005" in v
assert "Checks API" in v
# ── deny action is not a violation ──────────────────────────────────────────
def test_deny_action_not_violation():
"""A dangerous pattern with action=deny is not flagged (only allow is)."""
fake_rules = {"gh pr checks*": "deny"}
violations = cp.check_rules(fake_rules, "opencode.json")
assert violations == []
# ── gh pr merge in agent allow-list (CI guard, ADR-017) ──────────────────────
def test_gh_pr_merge_in_agent_detected(tmp_path, monkeypatch):
"""gh pr merge* in agent allow-list triggers violation (CI guard)."""
agent_file = tmp_path / "agents" / "reviewer.md"
agent_file.parent.mkdir(parents=True)
agent_file.write_text(
'---\nmode: subagent\npermission:\n bash:\n "gh pr merge*": allow\n---\ntest agent\n'
)
monkeypatch.setattr(cp, "AGENTS_DIR", tmp_path / "agents")
monkeypatch.setattr(cp, "OPENCODE_JSON", tmp_path / "nonexistent.json")
violations = cp.check_rules(
cp.parse_agent_bash_rules(agent_file),
f"agents/{agent_file.name}",
)
assert len(violations) == 1
assert "gh pr merge*" in violations[0]
assert "merge is done by main agent" in violations[0]
if __name__ == "__main__":
pytest.main([__file__, "-v"])