feat: new settings, CLI skeleton and interface skeletons
Adds the pydantic-settings Settings with validated GITEA_URL, OAuth scopes and toolsets, the argparse CLI skeleton, catalog.model, identity and GiteaAPIError. Test fixtures now isolate env, cwd and state paths in tmp.
This commit is contained in:
1 parent
4ac9626eb5
commit
b82e2866cb
24 files changed
+1512
-605
No files matched your search
+34
-4
@@ -11,8 +11,6 @@ from aegis_gitea_mcp.audit import AuditLogger, validate_audit_log_integrity
|
||||
def test_audit_log_integrity_valid(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Fresh audit log should validate with intact hash chain."""
|
||||
monkeypatch.setenv("GITEA_URL", "https://gitea.example.com")
|
||||
monkeypatch.setenv("GITEA_TOKEN", "token-123")
|
||||
monkeypatch.setenv("MCP_API_KEYS", "a" * 64)
|
||||
|
||||
log_path = tmp_path / "audit.log"
|
||||
logger = AuditLogger(log_path=log_path)
|
||||
@@ -30,8 +28,6 @@ def test_audit_log_integrity_detects_tamper(
|
||||
) -> None:
|
||||
"""Integrity validation should fail when entries are modified."""
|
||||
monkeypatch.setenv("GITEA_URL", "https://gitea.example.com")
|
||||
monkeypatch.setenv("GITEA_TOKEN", "token-123")
|
||||
monkeypatch.setenv("MCP_API_KEYS", "a" * 64)
|
||||
|
||||
log_path = tmp_path / "audit.log"
|
||||
logger = AuditLogger(log_path=log_path)
|
||||
@@ -48,3 +44,37 @@ def test_audit_log_integrity_detects_tamper(
|
||||
valid, errors = validate_audit_log_integrity(log_path)
|
||||
assert not valid
|
||||
assert errors
|
||||
|
||||
|
||||
def test_audit_logger_uses_configured_path(mock_env: None, tmp_path: Path) -> None:
|
||||
"""Without an explicit path the logger writes to AUDIT_LOG_PATH (tmp in tests)."""
|
||||
from aegis_gitea_mcp.audit import get_audit_logger
|
||||
|
||||
logger = get_audit_logger()
|
||||
logger.log_access_denied("tool", reason="nope")
|
||||
logger.log_security_event("evt", "description", metadata={"k": "v"})
|
||||
|
||||
assert logger.log_path == tmp_path / "data" / "audit.log"
|
||||
assert len(logger.log_path.read_text(encoding="utf-8").splitlines()) == 2
|
||||
valid, errors = validate_audit_log_integrity(logger.log_path)
|
||||
assert valid, errors
|
||||
|
||||
|
||||
def test_audit_masks_secrets_and_continues_chain(mock_env: None, tmp_path: Path) -> None:
|
||||
"""Secrets are masked before persistence and a reopened log continues the chain."""
|
||||
log_path = tmp_path / "chain.log"
|
||||
first = AuditLogger(log_path=log_path)
|
||||
first.log_tool_invocation("t", params={"note": "key AKIA1234567890ABCDEF"})
|
||||
first.close()
|
||||
second = AuditLogger(log_path=log_path)
|
||||
second.log_tool_invocation("t", error="boom", result_status="error")
|
||||
second.close()
|
||||
|
||||
text = log_path.read_text(encoding="utf-8")
|
||||
assert "AKIA1234567890ABCDEF" not in text
|
||||
valid, errors = validate_audit_log_integrity(log_path)
|
||||
assert valid, errors
|
||||
|
||||
|
||||
def test_validate_missing_log_is_valid(tmp_path: Path) -> None:
|
||||
assert validate_audit_log_integrity(tmp_path / "absent.log") == (True, [])
|
||||
Reference in new issue
Block a user