feat(github): authorize controlled backup execution
This commit is contained in:
@@ -19,10 +19,11 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary():
|
||||
assert data["summary"]["source_count"] == 5
|
||||
assert data["summary"]["loaded_source_count"] == 5
|
||||
assert data["summary"]["runtime_execution_authorized"] is False
|
||||
assert data["summary"]["remote_write_authorized"] is False
|
||||
assert data["summary"]["repo_creation_authorized"] is False
|
||||
assert data["summary"]["refs_sync_authorized"] is False
|
||||
assert data["summary"]["workflow_trigger_authorized"] is False
|
||||
assert data["summary"]["remote_write_authorized"] is True
|
||||
assert data["summary"]["repo_creation_authorized"] is True
|
||||
assert data["summary"]["visibility_change_authorized"] is True
|
||||
assert data["summary"]["refs_sync_authorized"] is True
|
||||
assert data["summary"]["workflow_trigger_authorized"] is True
|
||||
assert data["summary"]["secret_values_collected"] is False
|
||||
assert data["summary"]["average_completion_percent"] >= 0
|
||||
assert data["summary"]["high_risk_blocker_count"] > 0
|
||||
@@ -36,10 +37,16 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary():
|
||||
assert lanes["runtime"]["metric"]["kind"] == "surface_count"
|
||||
assert lanes["backup"]["metric"]["kind"] == "readiness_row_count"
|
||||
assert sources["github_private_backup"]["loaded"] is True
|
||||
assert sources["github_private_backup"]["schema_version"] == "github_target_private_backup_evidence_gate_v1"
|
||||
assert (
|
||||
sources["github_private_backup"]["schema_version"]
|
||||
== "github_target_private_backup_evidence_gate_v1"
|
||||
)
|
||||
assert sources["github_private_backup"]["missing_reason"] == ""
|
||||
assert lanes["github"]["blocker_count"] == 9
|
||||
assert lanes["github"]["status"] == "blocked_private_visibility_and_safe_credential_evidence_required"
|
||||
assert lanes["github"]["blocker_count"] == 0
|
||||
assert (
|
||||
lanes["github"]["status"]
|
||||
== "owner_authorized_controlled_execution_preflight_ready"
|
||||
)
|
||||
assert lanes["github"]["metric"]["verified"] == 4
|
||||
assert lanes["github"]["metric"]["total"] == 9
|
||||
assert all(0 <= lane["completion_percent"] <= 100 for lane in lanes.values())
|
||||
@@ -48,11 +55,11 @@ def test_delivery_closure_workbench_endpoint_returns_product_summary():
|
||||
boundaries = data["operation_boundaries"]
|
||||
assert boundaries["read_only_api_allowed"] is True
|
||||
assert boundaries["runtime_write_allowed"] is False
|
||||
assert boundaries["remote_write_allowed"] is False
|
||||
assert boundaries["repo_creation_allowed"] is False
|
||||
assert boundaries["visibility_change_allowed"] is False
|
||||
assert boundaries["refs_sync_allowed"] is False
|
||||
assert boundaries["workflow_trigger_allowed"] is False
|
||||
assert boundaries["remote_write_allowed"] is True
|
||||
assert boundaries["repo_creation_allowed"] is True
|
||||
assert boundaries["visibility_change_allowed"] is True
|
||||
assert boundaries["refs_sync_allowed"] is True
|
||||
assert boundaries["workflow_trigger_allowed"] is True
|
||||
assert boundaries["secret_value_collection_allowed"] is False
|
||||
assert boundaries["backup_restore_execution_allowed"] is False
|
||||
assert boundaries["active_scan_allowed"] is False
|
||||
|
||||
@@ -18,11 +18,10 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
snapshot = load_latest_github_target_private_backup_evidence_gate()
|
||||
|
||||
assert snapshot["schema_version"] == "github_target_private_backup_evidence_gate_v1"
|
||||
assert snapshot["mode"] == "read_only_private_backup_evidence_gate"
|
||||
assert (
|
||||
snapshot["status"]
|
||||
== "blocked_private_visibility_and_safe_credential_evidence_required"
|
||||
snapshot["mode"] == "owner_authorized_controlled_execution_no_secret_plaintext"
|
||||
)
|
||||
assert snapshot["status"] == "owner_authorized_controlled_execution_preflight_ready"
|
||||
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
|
||||
@@ -55,6 +54,13 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
== 0
|
||||
)
|
||||
assert snapshot["summary"]["github_missing_target_refs_sync_ready_count"] == 0
|
||||
assert (
|
||||
snapshot["summary"][
|
||||
"github_missing_target_create_private_repo_authorized_count"
|
||||
]
|
||||
== 5
|
||||
)
|
||||
assert snapshot["summary"]["github_missing_target_refs_sync_authorized_count"] == 5
|
||||
assert snapshot["summary"]["private_backup_verified_count"] == 4
|
||||
assert snapshot["summary"]["private_visibility_verified_count"] == 4
|
||||
assert snapshot["summary"]["safe_credential_required_count"] == 9
|
||||
@@ -90,17 +96,48 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
assert (
|
||||
snapshot["summary"]["github_target_owner_response_handoff_not_approval"] is True
|
||||
)
|
||||
assert snapshot["summary"]["blocked_target_count"] == 9
|
||||
assert snapshot["summary"]["owner_execution_authorization_received_count"] == 1
|
||||
assert snapshot["summary"]["owner_execution_authorized_target_count"] == 9
|
||||
assert (
|
||||
snapshot["summary"]["owner_execution_authorization_status"]
|
||||
== "owner_authorized_controlled_execution"
|
||||
)
|
||||
assert (
|
||||
snapshot["summary"]["owner_execution_authorization_source"]
|
||||
== "chat_authorization_2026-06-28_full_hard_gate_open"
|
||||
)
|
||||
assert (
|
||||
snapshot["summary"]["owner_execution_controlled_preflight_required_count"] == 9
|
||||
)
|
||||
assert snapshot["summary"]["post_execution_readback_required_count"] == 9
|
||||
assert snapshot["summary"]["execution_ready_count"] == 9
|
||||
assert snapshot["summary"]["blocked_target_count"] == 0
|
||||
assert snapshot["summary"]["public_repo_allowed"] is False
|
||||
assert snapshot["summary"]["repo_creation_authorized"] is False
|
||||
assert snapshot["summary"]["visibility_change_authorized"] is False
|
||||
assert snapshot["summary"]["refs_sync_authorized"] is False
|
||||
assert snapshot["summary"]["repo_creation_authorized"] is True
|
||||
assert snapshot["summary"]["visibility_change_authorized"] is True
|
||||
assert snapshot["summary"]["refs_sync_authorized"] is True
|
||||
assert snapshot["summary"]["workflow_trigger_authorized"] is True
|
||||
assert snapshot["summary"]["github_primary_switch_authorized"] is False
|
||||
assert snapshot["summary"]["secret_value_collection_allowed"] is False
|
||||
assert snapshot["operation_boundaries"]["read_only_api_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["repo_creation_allowed"] is False
|
||||
assert snapshot["operation_boundaries"]["visibility_change_allowed"] is False
|
||||
assert snapshot["operation_boundaries"]["refs_sync_allowed"] is False
|
||||
assert snapshot["operation_boundaries"]["github_api_write_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["repo_creation_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["visibility_change_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["refs_sync_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["workflow_trigger_allowed"] is True
|
||||
assert snapshot["operation_boundaries"]["secret_value_collection_allowed"] is False
|
||||
assert (
|
||||
snapshot["operation_boundaries"]["private_clone_url_collection_allowed"]
|
||||
is False
|
||||
)
|
||||
assert snapshot["authorization_flags"]["repo_creation_authorized"] is True
|
||||
assert snapshot["authorization_flags"]["visibility_change_authorized"] is True
|
||||
assert snapshot["authorization_flags"]["refs_sync_authorized"] is True
|
||||
assert snapshot["authorization_flags"]["workflow_trigger_authorized"] is True
|
||||
assert snapshot["authorization_flags"]["github_primary_switch_authorized"] is False
|
||||
assert (
|
||||
snapshot["authorization_flags"]["private_clone_url_collection_allowed"] is False
|
||||
)
|
||||
intake = snapshot["owner_response_intake_readiness"]
|
||||
assert (
|
||||
intake["status"]
|
||||
@@ -189,7 +226,7 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
)
|
||||
assert (
|
||||
targets["owenhytsai/awoooi"]["safe_credential_evidence_submission_status"]
|
||||
== "waiting_redacted_evidence_ref"
|
||||
== "owner_execution_authorized_post_apply_readback_pending"
|
||||
)
|
||||
assert (
|
||||
"redacted_metadata_pointer"
|
||||
@@ -210,6 +247,10 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
is False
|
||||
)
|
||||
assert targets["owenhytsai/awoooi"]["owner_response_execution_authorized"] is False
|
||||
assert targets["owenhytsai/awoooi"]["owner_execution_authorized"] is True
|
||||
assert targets["owenhytsai/awoooi"]["controlled_execution_ready"] is True
|
||||
assert targets["owenhytsai/awoooi"]["refs_sync_ready"] is True
|
||||
assert targets["owenhytsai/awoooi"]["blockers"] == []
|
||||
assert (
|
||||
"canonical_source"
|
||||
in targets["owenhytsai/awoooi"]["owner_response_required_fields"]
|
||||
@@ -226,6 +267,9 @@ def test_load_github_target_private_backup_evidence_gate_from_committed_snapshot
|
||||
is False
|
||||
)
|
||||
assert targets["owenhytsai/ewoooc"]["missing_target_refs_sync_ready"] is False
|
||||
assert targets["owenhytsai/ewoooc"]["repo_creation_authorized"] is True
|
||||
assert targets["owenhytsai/ewoooc"]["refs_sync_authorized"] is True
|
||||
assert targets["owenhytsai/ewoooc"]["execution_ready"] is True
|
||||
assert targets["owenhytsai/ewoooc"]["private_backup_verified"] is False
|
||||
assert (
|
||||
targets["owenhytsai/ewoooc"]["owner_response_template_id"]
|
||||
@@ -352,6 +396,21 @@ def test_github_target_private_backup_gate_rejects_missing_source_write_flags(tm
|
||||
load_latest_github_target_private_backup_evidence_gate(tmp_path)
|
||||
|
||||
|
||||
def test_github_target_private_backup_gate_rejects_execution_authorization_secrets(
|
||||
tmp_path,
|
||||
):
|
||||
_copy_security_snapshots(tmp_path)
|
||||
authorization_path = (
|
||||
tmp_path / "github-target-owner-execution-authorization.snapshot.json"
|
||||
)
|
||||
authorization = json.loads(authorization_path.read_text(encoding="utf-8"))
|
||||
authorization["summary"]["secret_value_collection_allowed"] = True
|
||||
authorization_path.write_text(json.dumps(authorization), encoding="utf-8")
|
||||
|
||||
with pytest.raises(ValueError, match="forbidden authorization flags"):
|
||||
load_latest_github_target_private_backup_evidence_gate(tmp_path)
|
||||
|
||||
|
||||
def test_github_target_owner_response_preflight_accepts_redacted_evidence_refs():
|
||||
preflight = preflight_github_target_owner_response_submission(
|
||||
_valid_owner_response_submission()
|
||||
@@ -439,8 +498,8 @@ def test_github_target_safe_credential_evidence_review_accepts_redacted_refs():
|
||||
assert payload["summary"]["safe_credential_evidence_submission_accepted_count"] == 1
|
||||
assert payload["summary"]["safe_credential_accepted_evidence_count"] == 0
|
||||
assert payload["summary"]["private_backup_verified_count"] == 4
|
||||
assert payload["summary"]["execution_ready_count"] == 0
|
||||
assert payload["summary"]["blocked_target_count"] == 9
|
||||
assert payload["summary"]["execution_ready_count"] == 9
|
||||
assert payload["summary"]["blocked_target_count"] == 0
|
||||
assert payload["boundaries"]["payload_persisted"] is False
|
||||
assert payload["boundaries"]["safe_credential_accepted_updated"] is False
|
||||
assert payload["boundaries"]["runtime_execution_authorized"] is False
|
||||
@@ -510,6 +569,7 @@ def _copy_security_snapshots(tmp_path: Path) -> None:
|
||||
"github-target-probe.snapshot.json",
|
||||
"github-target-connector-readback.snapshot.json",
|
||||
"github-target-missing-source-readiness.snapshot.json",
|
||||
"github-target-owner-execution-authorization.snapshot.json",
|
||||
):
|
||||
shutil.copy(source_dir / filename, tmp_path / filename)
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ def test_github_target_private_backup_evidence_gate_endpoint_returns_read_only_g
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["schema_version"] == "github_target_private_backup_evidence_gate_v1"
|
||||
assert data["mode"] == "read_only_private_backup_evidence_gate"
|
||||
assert data["mode"] == "owner_authorized_controlled_execution_no_secret_plaintext"
|
||||
assert data["status"] == "owner_authorized_controlled_execution_preflight_ready"
|
||||
assert data["summary"]["approval_required_target_count"] == 9
|
||||
assert data["summary"]["github_connector_readback_count"] == 9
|
||||
assert data["summary"]["github_connector_private_visibility_count"] == 4
|
||||
@@ -25,6 +26,11 @@ def test_github_target_private_backup_evidence_gate_endpoint_returns_read_only_g
|
||||
assert data["summary"]["github_missing_target_gitea_source_candidate_count"] == 3
|
||||
assert data["summary"]["github_missing_target_create_private_repo_ready_count"] == 0
|
||||
assert data["summary"]["github_missing_target_refs_sync_ready_count"] == 0
|
||||
assert (
|
||||
data["summary"]["github_missing_target_create_private_repo_authorized_count"]
|
||||
== 5
|
||||
)
|
||||
assert data["summary"]["github_missing_target_refs_sync_authorized_count"] == 5
|
||||
assert data["summary"]["private_backup_verified_count"] == 4
|
||||
assert data["summary"]["private_visibility_verified_count"] == 4
|
||||
assert data["summary"]["safe_credential_evidence_intake_ready"] is True
|
||||
@@ -46,18 +52,22 @@ def test_github_target_private_backup_evidence_gate_endpoint_returns_read_only_g
|
||||
assert data["summary"]["owner_response_collection_check_count"] == 6
|
||||
assert data["summary"]["owner_response_intake_preflight_check_count"] == 6
|
||||
assert data["summary"]["owner_response_request_execution_authorized"] is False
|
||||
assert data["summary"]["blocked_target_count"] == 9
|
||||
assert data["summary"]["owner_execution_authorization_received_count"] == 1
|
||||
assert data["summary"]["owner_execution_authorized_target_count"] == 9
|
||||
assert data["summary"]["execution_ready_count"] == 9
|
||||
assert data["summary"]["blocked_target_count"] == 0
|
||||
assert data["summary"]["public_repo_allowed"] is False
|
||||
assert data["summary"]["repo_creation_authorized"] is False
|
||||
assert data["summary"]["visibility_change_authorized"] is False
|
||||
assert data["summary"]["refs_sync_authorized"] is False
|
||||
assert data["summary"]["repo_creation_authorized"] is True
|
||||
assert data["summary"]["visibility_change_authorized"] is True
|
||||
assert data["summary"]["refs_sync_authorized"] is True
|
||||
assert data["summary"]["workflow_trigger_authorized"] is True
|
||||
assert data["summary"]["secret_value_collection_allowed"] is False
|
||||
assert data["operation_boundaries"]["read_only_api_allowed"] is True
|
||||
assert data["operation_boundaries"]["github_api_write_allowed"] is False
|
||||
assert data["operation_boundaries"]["repo_creation_allowed"] is False
|
||||
assert data["operation_boundaries"]["visibility_change_allowed"] is False
|
||||
assert data["operation_boundaries"]["refs_sync_allowed"] is False
|
||||
assert data["operation_boundaries"]["workflow_trigger_allowed"] is False
|
||||
assert data["operation_boundaries"]["github_api_write_allowed"] is True
|
||||
assert data["operation_boundaries"]["repo_creation_allowed"] is True
|
||||
assert data["operation_boundaries"]["visibility_change_allowed"] is True
|
||||
assert data["operation_boundaries"]["refs_sync_allowed"] is True
|
||||
assert data["operation_boundaries"]["workflow_trigger_allowed"] is True
|
||||
assert data["operation_boundaries"]["private_clone_url_collection_allowed"] is False
|
||||
intake = data["owner_response_intake_readiness"]
|
||||
assert (
|
||||
@@ -92,9 +102,11 @@ def test_github_target_private_backup_evidence_gate_endpoint_returns_read_only_g
|
||||
== "/api/v1/agents/github-target-safe-credential-evidence-reviewer-validation/validate-redacted-refs"
|
||||
)
|
||||
assert data["targets"][0]["owner_response_execution_authorized"] is False
|
||||
assert data["targets"][0]["owner_execution_authorized"] is True
|
||||
assert data["targets"][0]["controlled_execution_ready"] is True
|
||||
assert (
|
||||
data["targets"][0]["safe_credential_evidence_submission_status"]
|
||||
== "waiting_redacted_evidence_ref"
|
||||
== "owner_execution_authorized_post_apply_readback_pending"
|
||||
)
|
||||
assert data["targets"][0]["safe_credential_raw_payload_storage_allowed"] is False
|
||||
assert (
|
||||
@@ -211,5 +223,5 @@ def test_github_target_safe_credential_evidence_review_api_does_not_persist():
|
||||
== 0
|
||||
)
|
||||
assert readback["summary"]["github_missing_target_refs_sync_ready_count"] == 0
|
||||
assert readback["summary"]["execution_ready_count"] == 0
|
||||
assert readback["summary"]["execution_ready_count"] == 9
|
||||
assert "192.168.0." not in response.text
|
||||
|
||||
Reference in New Issue
Block a user