fix(windows99): project scoped relink dry run
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m14s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 43s
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m14s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 43s
This commit is contained in:
@@ -35,6 +35,9 @@ _CANDIDATE_CONFIRMATION_VALIDATION_SCHEMA_VERSION = (
|
||||
_CANDIDATE_CONFIRMATION_PACKET_SCHEMA_VERSION = (
|
||||
"windows99_vmx_source_candidate_confirmation_packet_v1"
|
||||
)
|
||||
_SCOPED_RELINK_DRY_RUN_SCHEMA_VERSION = (
|
||||
"windows99_vmx_source_scoped_relink_dry_run_v1"
|
||||
)
|
||||
_RECEIPT_FILE = "windows99-vmx-source-locator-receipt.snapshot.json"
|
||||
_COLLECTOR_SCRIPT_PATH = "scripts/reboot-recovery/locate-windows99-vmx-source.sh"
|
||||
_LOCATOR_SCRIPT_PATH = "scripts/reboot-recovery/windows99-vmx-source-locator.ps1"
|
||||
@@ -289,6 +292,104 @@ def _build_candidate_confirmation_gate(
|
||||
}
|
||||
|
||||
|
||||
def _build_projected_scoped_relink_dry_run_plan(
|
||||
*,
|
||||
accepted: bool,
|
||||
locator: dict[str, Any],
|
||||
packet: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
target_aliases = _strings(locator.get("target_vm_aliases"))
|
||||
missing_aliases = _strings(locator.get("missing_vmx_aliases")) or target_aliases
|
||||
evidence_ref = (
|
||||
str(packet.get("candidate_identity_evidence_ref") or "").strip()
|
||||
if accepted
|
||||
else ""
|
||||
)
|
||||
candidate_identity_kind = (
|
||||
str(packet.get("candidate_identity_kind") or "").strip() if accepted else ""
|
||||
)
|
||||
ready = bool(accepted)
|
||||
existing_plan = _dict(locator.get("controlled_relink_dry_run_plan"))
|
||||
|
||||
return {
|
||||
"schema_version": _SCOPED_RELINK_DRY_RUN_SCHEMA_VERSION,
|
||||
"plan_id": (
|
||||
"windows99-vmx-source-relink-dry-run-"
|
||||
f"{','.join(missing_aliases) or 'none'}"
|
||||
),
|
||||
"status": (
|
||||
"ready_for_no_write_review"
|
||||
if ready
|
||||
else "blocked_candidate_confirmation_not_accepted"
|
||||
),
|
||||
"ready": ready,
|
||||
"mode": "dry_run_no_windows_or_vm_write",
|
||||
"target_selector": {
|
||||
"host_alias": "99",
|
||||
"vm_aliases": target_aliases,
|
||||
"missing_vmx_aliases": missing_aliases,
|
||||
"candidate_identity_kind": candidate_identity_kind,
|
||||
"secret_collection_allowed": False,
|
||||
"vm_power_change_allowed": False,
|
||||
"runtime_write_allowed": False,
|
||||
},
|
||||
"source_diff": {
|
||||
"expected_vmx_path_count": locator.get("expected_vmx_path_count"),
|
||||
"expected_vmx_path_present_count": locator.get(
|
||||
"expected_vmx_path_present_count"
|
||||
),
|
||||
"candidate_source_count": locator.get("candidate_source_count"),
|
||||
"candidate_source_fingerprint_count": locator.get(
|
||||
"candidate_source_fingerprint_count"
|
||||
),
|
||||
"alias_hint_candidate_count": locator.get("alias_hint_candidate_count"),
|
||||
"identity_target_hint_count": locator.get("identity_target_hint_count"),
|
||||
"identity_unassigned_ubuntu_candidate_count": locator.get(
|
||||
"identity_unassigned_ubuntu_candidate_count"
|
||||
),
|
||||
"candidate_identity_evidence_ref": evidence_ref,
|
||||
"raw_path_output": False,
|
||||
"path_fingerprint_only": True,
|
||||
"bounded_identity_metadata_only": True,
|
||||
},
|
||||
"pre_apply_backup_plan": {
|
||||
"required": True,
|
||||
"status": (
|
||||
"review_required_before_apply"
|
||||
if ready
|
||||
else "blocked_candidate_confirmation_not_accepted"
|
||||
),
|
||||
"backup_ref_required": True,
|
||||
"rollback_ref": "rollback://awoooi/windows99-vmx-source-relink-dry-run",
|
||||
},
|
||||
"rollback_ref": "rollback://awoooi/windows99-vmx-source-relink-dry-run",
|
||||
"post_verifier": [
|
||||
"bash scripts/reboot-recovery/collect-windows99-vmware-verify.sh --collect",
|
||||
"GET /api/v1/agents/reboot-auto-recovery-slo-scorecard",
|
||||
"GET /api/v1/agents/windows99-vmx-source-repair-package",
|
||||
"GET /api/v1/agents/windows99-vmx-source-locator-readback",
|
||||
],
|
||||
"km_writeback_ref": (
|
||||
str(existing_plan.get("km_writeback_ref") or "")
|
||||
or "km://awoooi/reboot-slo/windows99-vmx-source-locator-111"
|
||||
),
|
||||
"playbook_trust_writeback_ref": (
|
||||
str(existing_plan.get("playbook_trust_writeback_ref") or "")
|
||||
or "playbook://awoooi/windows99-vmx-source-locator/windows99-vmx-source-locator-111"
|
||||
),
|
||||
"apply_allowed_by_this_plan": False,
|
||||
"remote_write_performed": False,
|
||||
"vm_power_change_performed": False,
|
||||
"secret_value_read": False,
|
||||
"request_payload_saved": False,
|
||||
"safe_next_step": (
|
||||
"review_scoped_relink_dry_run_then_run_post_verifier_no_vm_power_change"
|
||||
if ready
|
||||
else "submit_redacted_single_candidate_identity_evidence_without_raw_paths"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def validate_windows99_vmx_source_candidate_confirmation_packet(
|
||||
packet: dict[str, Any],
|
||||
*,
|
||||
@@ -362,6 +463,13 @@ def validate_windows99_vmx_source_candidate_confirmation_packet(
|
||||
if accepted
|
||||
else "submit_redacted_single_candidate_identity_evidence_without_raw_paths"
|
||||
)
|
||||
projected_scoped_relink_dry_run_plan = (
|
||||
_build_projected_scoped_relink_dry_run_plan(
|
||||
accepted=accepted,
|
||||
locator=locator,
|
||||
packet=packet,
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
"schema_version": _CANDIDATE_CONFIRMATION_VALIDATION_SCHEMA_VERSION,
|
||||
@@ -398,6 +506,14 @@ def validate_windows99_vmx_source_candidate_confirmation_packet(
|
||||
"secret_value_read": False,
|
||||
"safe_next_step": next_safe_step,
|
||||
},
|
||||
"scoped_relink_dry_run_ready": accepted,
|
||||
"pre_apply_backup_plan_ready": accepted,
|
||||
"post_verifier_ready": accepted,
|
||||
"km_writeback_ready": accepted,
|
||||
"playbook_trust_writeback_ready": accepted,
|
||||
"projected_scoped_relink_dry_run_plan": (
|
||||
projected_scoped_relink_dry_run_plan
|
||||
),
|
||||
"operation_boundaries": {
|
||||
"no_persist_validator": True,
|
||||
"request_payload_saved": False,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://test:test@localhost/test")
|
||||
@@ -273,6 +274,40 @@ def test_windows99_candidate_confirmation_validator_accepts_redacted_packet() ->
|
||||
assert payload["projected_confirmation_gate"][
|
||||
"apply_allowed_by_confirmation_gate"
|
||||
] is False
|
||||
assert payload["scoped_relink_dry_run_ready"] is True
|
||||
assert payload["pre_apply_backup_plan_ready"] is True
|
||||
assert payload["post_verifier_ready"] is True
|
||||
assert payload["km_writeback_ready"] is True
|
||||
assert payload["playbook_trust_writeback_ready"] is True
|
||||
plan = payload["projected_scoped_relink_dry_run_plan"]
|
||||
assert plan["schema_version"] == "windows99_vmx_source_scoped_relink_dry_run_v1"
|
||||
assert plan["status"] == "ready_for_no_write_review"
|
||||
assert plan["ready"] is True
|
||||
assert plan["mode"] == "dry_run_no_windows_or_vm_write"
|
||||
assert plan["target_selector"]["host_alias"] == "99"
|
||||
assert plan["target_selector"]["vm_aliases"] == ["111"]
|
||||
assert plan["target_selector"]["missing_vmx_aliases"] == ["111"]
|
||||
assert plan["target_selector"]["secret_collection_allowed"] is False
|
||||
assert plan["target_selector"]["vm_power_change_allowed"] is False
|
||||
assert plan["target_selector"]["runtime_write_allowed"] is False
|
||||
assert plan["source_diff"]["candidate_identity_evidence_ref"] == (
|
||||
"console://awoooi/windows99/candidate-identity-redacted-111"
|
||||
)
|
||||
assert plan["source_diff"]["raw_path_output"] is False
|
||||
assert plan["source_diff"]["path_fingerprint_only"] is True
|
||||
assert plan["pre_apply_backup_plan"]["required"] is True
|
||||
assert plan["pre_apply_backup_plan"]["backup_ref_required"] is True
|
||||
assert plan["rollback_ref"] == (
|
||||
"rollback://awoooi/windows99-vmx-source-relink-dry-run"
|
||||
)
|
||||
assert "GET /api/v1/agents/windows99-vmx-source-locator-readback" in plan[
|
||||
"post_verifier"
|
||||
]
|
||||
assert plan["apply_allowed_by_this_plan"] is False
|
||||
assert plan["remote_write_performed"] is False
|
||||
assert plan["vm_power_change_performed"] is False
|
||||
assert plan["secret_value_read"] is False
|
||||
assert plan["request_payload_saved"] is False
|
||||
assert payload["operation_boundaries"]["request_payload_saved"] is False
|
||||
assert payload["operation_boundaries"]["remote_write_performed"] is False
|
||||
assert payload["operation_boundaries"]["vm_power_change_performed"] is False
|
||||
@@ -325,6 +360,14 @@ def test_windows99_candidate_confirmation_validator_rejects_sensitive_payload()
|
||||
assert payload["projected_confirmation_gate"][
|
||||
"can_prepare_scoped_relink_dry_run"
|
||||
] is False
|
||||
assert payload["scoped_relink_dry_run_ready"] is False
|
||||
plan = payload["projected_scoped_relink_dry_run_plan"]
|
||||
assert plan["ready"] is False
|
||||
assert plan["status"] == "blocked_candidate_confirmation_not_accepted"
|
||||
assert plan["source_diff"]["candidate_identity_evidence_ref"] == ""
|
||||
serialized = json.dumps(payload)
|
||||
assert "D:\\" not in serialized
|
||||
assert "192.168.0." not in serialized
|
||||
assert payload["operation_boundaries"]["apply_gate_opened"] is False
|
||||
|
||||
|
||||
@@ -453,5 +496,14 @@ def test_windows99_candidate_confirmation_endpoint_is_no_persist_validator(
|
||||
assert payload["operation_boundaries"]["request_payload_saved"] is False
|
||||
assert payload["operation_boundaries"]["apply_gate_opened"] is False
|
||||
assert payload["operation_boundaries"]["vm_power_change_performed"] is False
|
||||
assert payload["scoped_relink_dry_run_ready"] is True
|
||||
plan = payload["projected_scoped_relink_dry_run_plan"]
|
||||
assert plan["ready"] is True
|
||||
assert plan["mode"] == "dry_run_no_windows_or_vm_write"
|
||||
assert plan["source_diff"]["candidate_identity_evidence_ref"] == (
|
||||
"backup://awoooi/windows99/redacted-fingerprint-111"
|
||||
)
|
||||
assert plan["apply_allowed_by_this_plan"] is False
|
||||
assert plan["request_payload_saved"] is False
|
||||
assert "D:\\" not in response.text
|
||||
assert "192.168.0." not in response.text
|
||||
|
||||
Reference in New Issue
Block a user