feat(github): expose owner private backup readback summary

This commit is contained in:
Your Name
2026-06-27 12:13:48 +08:00
parent cc1c10704a
commit 3dcb67ffb6
2 changed files with 17 additions and 0 deletions

View File

@@ -60,6 +60,7 @@ def build_github_target_private_backup_evidence_gate(
) -> dict[str, Any]:
"""Build the read-only gate response from source-control snapshots."""
connector_payload = _dict(connector_readback)
owner_readback = _dict(connector_payload.get("owner_readback"))
decisions = [_dict(row) for row in _list(decision.get("decisions"))]
probe_by_repo = {
str(row.get("github_repo")): _dict(row)
@@ -129,6 +130,12 @@ def build_github_target_private_backup_evidence_gate(
"target_decision_count": len(targets),
"approval_required_target_count": len(approval_required_targets),
"approval_package_item_count": len(_list(approval_package.get("approval_items"))),
"github_connector_owner_visible_repository_count": _int(
owner_readback.get("visible_repository_count")
),
"github_connector_owner_visible_private_repository_count": _int(
owner_readback.get("visible_private_repository_count")
),
"github_connector_readback_count": len(_list(connector_payload.get("targets"))),
"github_connector_private_visibility_count": sum(
1
@@ -366,9 +373,16 @@ def _require_approval_package_consistency(payload: dict[str, Any], label: str) -
def _require_connector_readback_consistency(payload: dict[str, Any], label: str) -> None:
summary = _dict(payload.get("summary"))
owner_readback = _dict(payload.get("owner_readback"))
targets = [_dict(row) for row in _list(payload.get("targets"))]
if _int(summary.get("target_count")) != len(targets):
raise ValueError(f"{label}: summary.target_count must equal targets length")
if owner_readback:
visible_repositories = _list(owner_readback.get("visible_repositories"))
if _int(owner_readback.get("visible_repository_count")) != len(visible_repositories):
raise ValueError(f"{label}: owner visible repository count must match visible repositories")
if _int(owner_readback.get("visible_private_repository_count")) > len(visible_repositories):
raise ValueError(f"{label}: owner private repository count cannot exceed visible repositories")
private_count = sum(1 for row in targets if row.get("private_visibility_verified") is True)
not_found_count = sum(1 for row in targets if row.get("readback_status") == "not_found_or_inaccessible")
if _int(summary.get("private_visibility_verified_count")) != private_count:
@@ -383,6 +397,7 @@ def _require_connector_readback_consistency(payload: dict[str, Any], label: str)
"secret_values_collected",
}
enabled = sorted(flag for flag in false_flags if summary.get(flag) is not False)
enabled.extend(sorted(flag for flag in false_flags if owner_readback and owner_readback.get(flag) is not False))
if enabled:
raise ValueError(f"{label}: connector readback must remain read-only: {enabled}")

View File

@@ -20,6 +20,8 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
assert snapshot["status"] == "blocked_private_visibility_and_safe_credential_evidence_required"
assert snapshot["summary"]["target_decision_count"] == 10
assert snapshot["summary"]["approval_required_target_count"] == 9
assert snapshot["summary"]["github_connector_owner_visible_repository_count"] == 4
assert snapshot["summary"]["github_connector_owner_visible_private_repository_count"] == 4
assert snapshot["summary"]["github_connector_readback_count"] == 9
assert snapshot["summary"]["github_connector_private_visibility_count"] == 4
assert snapshot["summary"]["github_connector_not_found_or_inaccessible_count"] == 5