from agent import RepoFile, _analyze_repository, _redact_secrets from a2a_pack.context import LLMCreds def test_analysis_detects_security_dependency_tests_docs_and_scores(): files = [ RepoFile( path="app.py", size=80, sha="a", category="source", text="DEBUG = True\nAPI_KEY='abcdef1234567890'\n# TODO fix auth\n", lines=["DEBUG = True", "API_KEY='abcdef1234567890'", "# TODO fix auth", ""], ), RepoFile( path="requirements.txt", size=30, sha="b", category="package/dependency", text="fastapi\nuvicorn==0.30.0\n", lines=["fastapi", "uvicorn==0.30.0", ""], ), RepoFile( path="Dockerfile", size=30, sha="c", category="Docker/container", text="FROM python\n", lines=["FROM python", ""], ), ] tree_entries = [ {"path": "app.py", "type": "blob"}, {"path": "requirements.txt", "type": "blob"}, {"path": "Dockerfile", "type": "blob"}, ] classified = { "counts_by_category": {"source": 1, "package/dependency": 1, "Docker/container": 1, "tests": 0, "docs": 0, "CI/CD": 0}, "tree": [], "categories": {}, "total_entries": 3, "total_files": 3, } report = _analyze_repository( repo_meta={"owner": {"login": "octo"}, "name": "demo", "full_name": "octo/demo", "default_branch": "main"}, ref="main", branches=[], tree_entries=tree_entries, classified=classified, files=files, skipped=[], limits={"max_files": 100, "max_bytes": 1000, "max_file_bytes": 1000}, llm_creds=LLMCreds(base_url="", api_key="", model="", source="platform"), ) categories = {f["category"] for f in report["findings"]} assert "security/config" in categories assert "dependency" in categories assert "tests" in categories assert "docs" in categories assert report["scorecard"]["total"] < 90 assert any(c["path"] == "app.py" and "REDACTED" in c["snippet"] for f in report["findings"] for c in f["citations"]) def test_redacts_secret_like_values(): text = "API_KEY=sk_test_1234567890abcdef" assert "sk_test_1234567890abcdef" not in _redact_secrets(text) assert "" in _redact_secrets(text)