fix(reboot): project vmx locator receipt readback
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 3m47s
CD Pipeline / build-and-deploy (push) Successful in 4m48s
CD Pipeline / post-deploy-checks (push) Successful in 1m52s
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 3m47s
CD Pipeline / build-and-deploy (push) Successful in 4m48s
CD Pipeline / post-deploy-checks (push) Successful in 1m52s
This commit is contained in:
@@ -3457,6 +3457,24 @@ def _enrich_from_current_readbacks(
|
||||
state["windows99_vmx_source_locator_expected_vmx_path_count"] = _int(
|
||||
windows99_vmx_source_locator_readback.get("expected_vmx_path_count")
|
||||
)
|
||||
state["windows99_vmx_source_locator_candidate_source_count"] = _int(
|
||||
windows99_vmx_source_locator_readback.get("candidate_source_count")
|
||||
)
|
||||
state["windows99_vmx_source_locator_alias_hint_candidate_count"] = _int(
|
||||
windows99_vmx_source_locator_readback.get("alias_hint_candidate_count")
|
||||
)
|
||||
state["windows99_vmx_source_locator_unassigned_ubuntu_candidate_count"] = _int(
|
||||
windows99_vmx_source_locator_readback.get("unassigned_ubuntu_candidate_count")
|
||||
)
|
||||
state["windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"] = _int(
|
||||
windows99_vmx_source_locator_readback.get(
|
||||
"identity_unassigned_ubuntu_candidate_count"
|
||||
)
|
||||
)
|
||||
state["windows99_vmx_source_locator_candidate_confirmation_required"] = bool(
|
||||
windows99_vmx_source_locator_readback.get("candidate_confirmation_required")
|
||||
is True
|
||||
)
|
||||
state["windows99_vmx_source_locator_candidate_source_count_known"] = bool(
|
||||
windows99_vmx_source_locator_readback.get("candidate_source_count_known")
|
||||
is True
|
||||
@@ -3856,6 +3874,23 @@ def _enrich_from_current_readbacks(
|
||||
evidence["windows99_vmx_source_locator_expected_vmx_path_count"] = state[
|
||||
"windows99_vmx_source_locator_expected_vmx_path_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_locator_candidate_source_count"] = state[
|
||||
"windows99_vmx_source_locator_candidate_source_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_locator_alias_hint_candidate_count"] = state[
|
||||
"windows99_vmx_source_locator_alias_hint_candidate_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_locator_unassigned_ubuntu_candidate_count"] = state[
|
||||
"windows99_vmx_source_locator_unassigned_ubuntu_candidate_count"
|
||||
]
|
||||
evidence[
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
] = state[
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
]
|
||||
evidence["windows99_vmx_source_locator_candidate_confirmation_required"] = state[
|
||||
"windows99_vmx_source_locator_candidate_confirmation_required"
|
||||
]
|
||||
evidence["windows99_vmx_source_locator_candidate_source_count_known"] = state[
|
||||
"windows99_vmx_source_locator_candidate_source_count_known"
|
||||
]
|
||||
@@ -4630,6 +4665,24 @@ def _set_rollups_and_summary(
|
||||
"windows99_vmx_source_locator_expected_vmx_path_count": _int(
|
||||
state.get("windows99_vmx_source_locator_expected_vmx_path_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_source_count": _int(
|
||||
state.get("windows99_vmx_source_locator_candidate_source_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_alias_hint_candidate_count": _int(
|
||||
state.get("windows99_vmx_source_locator_alias_hint_candidate_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_unassigned_ubuntu_candidate_count": _int(
|
||||
state.get("windows99_vmx_source_locator_unassigned_ubuntu_candidate_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count": _int(
|
||||
state.get(
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
)
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_confirmation_required": (
|
||||
state.get("windows99_vmx_source_locator_candidate_confirmation_required")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_source_count_known": (
|
||||
state.get("windows99_vmx_source_locator_candidate_source_count_known")
|
||||
is True
|
||||
@@ -4934,6 +4987,24 @@ def _set_rollups_and_summary(
|
||||
"windows99_vmx_source_locator_expected_vmx_path_count": _int(
|
||||
state.get("windows99_vmx_source_locator_expected_vmx_path_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_source_count": _int(
|
||||
state.get("windows99_vmx_source_locator_candidate_source_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_alias_hint_candidate_count": _int(
|
||||
state.get("windows99_vmx_source_locator_alias_hint_candidate_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_unassigned_ubuntu_candidate_count": _int(
|
||||
state.get("windows99_vmx_source_locator_unassigned_ubuntu_candidate_count")
|
||||
),
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count": _int(
|
||||
state.get(
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
)
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_confirmation_required": (
|
||||
state.get("windows99_vmx_source_locator_candidate_confirmation_required")
|
||||
is True
|
||||
),
|
||||
"windows99_vmx_source_locator_candidate_source_count_known": (
|
||||
state.get("windows99_vmx_source_locator_candidate_source_count_known")
|
||||
is True
|
||||
|
||||
@@ -8,19 +8,25 @@ start VMs, stop VMs, restart services, or reboot hosts.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from src.services.reboot_auto_recovery_slo_scorecard import (
|
||||
_taipei_now_iso,
|
||||
load_latest_reboot_auto_recovery_slo_scorecard,
|
||||
)
|
||||
from src.services.snapshot_paths import default_operations_dir
|
||||
from src.services.windows99_vmx_source_repair_package import (
|
||||
build_windows99_vmx_source_repair_package,
|
||||
)
|
||||
|
||||
_DEFAULT_OPERATIONS_DIR = default_operations_dir(Path(__file__))
|
||||
_SCHEMA_VERSION = "windows99_vmx_source_locator_readback_v1"
|
||||
_COLLECTOR_SCHEMA_VERSION = "windows99_vmx_source_locator_collector_v1"
|
||||
_LOCATOR_SCHEMA_VERSION = "windows99_vmx_source_locator_v1"
|
||||
_RECEIPT_SCHEMA_VERSION = "windows99_vmx_source_locator_receipt_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"
|
||||
|
||||
@@ -41,6 +47,33 @@ def _bool(value: Any) -> bool:
|
||||
return value is True
|
||||
|
||||
|
||||
def _int(value: Any, default: int | None = None) -> int | None:
|
||||
if isinstance(value, bool):
|
||||
return default
|
||||
if isinstance(value, int):
|
||||
return value
|
||||
if isinstance(value, str) and value.strip().isdigit():
|
||||
return int(value.strip())
|
||||
return default
|
||||
|
||||
|
||||
def _load_locator_receipt(operations_dir: Path | None = None) -> dict[str, Any]:
|
||||
path = (operations_dir or _DEFAULT_OPERATIONS_DIR) / _RECEIPT_FILE
|
||||
if not path.exists():
|
||||
return {}
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
if not isinstance(payload, dict):
|
||||
raise ValueError(f"{path}: expected JSON object")
|
||||
if payload.get("schema_version") != _RECEIPT_SCHEMA_VERSION:
|
||||
raise ValueError(f"{path}: unexpected schema_version")
|
||||
serialized = json.dumps(payload, ensure_ascii=False)
|
||||
forbidden = ["192.168.0.", "D:\\", "C:\\", "E:\\", "uuid.", "generatedAddress"]
|
||||
leaked = [fragment for fragment in forbidden if fragment in serialized]
|
||||
if leaked:
|
||||
raise ValueError(f"{path}: unsafe locator receipt fragments: {leaked}")
|
||||
return payload
|
||||
|
||||
|
||||
def _vm_rows_for_aliases(
|
||||
repair_package: dict[str, Any],
|
||||
target_aliases: list[str],
|
||||
@@ -60,6 +93,8 @@ def build_windows99_vmx_source_locator_readback(
|
||||
scorecard: dict[str, Any],
|
||||
*,
|
||||
repair_package: dict[str, Any] | None = None,
|
||||
collector_receipt: dict[str, Any] | None = None,
|
||||
operations_dir: Path | None = None,
|
||||
generated_at: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
package = repair_package or build_windows99_vmx_source_repair_package(scorecard)
|
||||
@@ -111,6 +146,21 @@ def build_windows99_vmx_source_locator_readback(
|
||||
"--collect"
|
||||
)
|
||||
|
||||
receipt = collector_receipt if collector_receipt is not None else _load_locator_receipt(operations_dir)
|
||||
receipt = _dict(receipt)
|
||||
receipt_aliases = _strings(receipt.get("target_vm_aliases"))
|
||||
receipt_applies = bool(
|
||||
receipt.get("collector_readback_present") is True
|
||||
and receipt.get("target_host_alias") == "99"
|
||||
and receipt_aliases
|
||||
and set(receipt_aliases).issubset(set(target_aliases or receipt_aliases))
|
||||
)
|
||||
receipt_locate_status = str(receipt.get("locate_status") or "")
|
||||
if receipt_applies:
|
||||
status = "collector_readback_single_identity_candidate_confirmation_required"
|
||||
next_step = "confirm_single_unassigned_ubuntu_candidate_before_scoped_relink_dry_run"
|
||||
safe_next_step = str(receipt.get("safe_next_step") or safe_next_step)
|
||||
|
||||
return {
|
||||
"schema_version": _SCHEMA_VERSION,
|
||||
"generated_at": generated_at
|
||||
@@ -127,8 +177,14 @@ def build_windows99_vmx_source_locator_readback(
|
||||
"locator_script_path": _LOCATOR_SCRIPT_PATH,
|
||||
"collector_schema_version": _COLLECTOR_SCHEMA_VERSION,
|
||||
"locator_schema_version": _LOCATOR_SCHEMA_VERSION,
|
||||
"collector_readback_present": False,
|
||||
"collector_collection_status": "not_collected_by_api_readback",
|
||||
"collector_readback_present": receipt_applies,
|
||||
"collector_receipt_ref": str(receipt.get("receipt_ref") or "") if receipt_applies else "",
|
||||
"collector_receipt_generated_at": str(receipt.get("generated_at") or "") if receipt_applies else "",
|
||||
"collector_collection_status": (
|
||||
str(receipt.get("collector_collection_status") or "")
|
||||
if receipt_applies
|
||||
else "not_collected_by_api_readback"
|
||||
),
|
||||
"management_channel_ready": management_channel_ready,
|
||||
"can_collect_vmware_verify_without_secret": (
|
||||
can_collect_vmware_verify_without_secret
|
||||
@@ -143,15 +199,57 @@ def build_windows99_vmx_source_locator_readback(
|
||||
),
|
||||
"remote_locator_mode": "in_memory_stdin_scriptblock",
|
||||
"expected_vmx_path_count": expected_vmx_path_count,
|
||||
"expected_vmx_path_present_count": None,
|
||||
"candidate_source_count": None,
|
||||
"candidate_source_count_known": False,
|
||||
"candidate_source_fingerprint_count": None,
|
||||
"expected_vmx_path_present_count": (
|
||||
_int(receipt.get("expected_vmx_path_present_count"))
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"candidate_source_count": (
|
||||
_int(receipt.get("candidate_source_count")) if receipt_applies else None
|
||||
),
|
||||
"candidate_source_count_known": bool(receipt_applies),
|
||||
"candidate_source_fingerprint_count": (
|
||||
_int(receipt.get("candidate_source_fingerprint_count"), 0)
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"alias_hint_candidate_count": (
|
||||
_int(receipt.get("alias_hint_candidate_count"), 0)
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"unassigned_ubuntu_candidate_count": (
|
||||
_int(receipt.get("unassigned_ubuntu_candidate_count"), 0)
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"identity_metadata_read": bool(
|
||||
receipt_applies and receipt.get("identity_metadata_read") is True
|
||||
),
|
||||
"identity_target_hint_count": (
|
||||
_int(receipt.get("identity_target_hint_count"), 0)
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"identity_unassigned_ubuntu_candidate_count": (
|
||||
_int(receipt.get("identity_unassigned_ubuntu_candidate_count"), 0)
|
||||
if receipt_applies
|
||||
else None
|
||||
),
|
||||
"locate_status": receipt_locate_status if receipt_applies else "",
|
||||
"candidate_confirmation_required": bool(
|
||||
receipt_applies and "requires_confirmation" in receipt_locate_status
|
||||
),
|
||||
"public_lan_topology_redacted": True,
|
||||
"redacted_public_display_only": True,
|
||||
"raw_path_output": False,
|
||||
"path_fingerprint_only": True,
|
||||
"file_content_read": False,
|
||||
"file_content_read": bool(
|
||||
receipt_applies and receipt.get("identity_metadata_read") is True
|
||||
),
|
||||
"bounded_identity_metadata_only": bool(
|
||||
receipt_applies and receipt.get("bounded_identity_metadata_only") is True
|
||||
),
|
||||
"secret_value_read": False,
|
||||
"password_prompt_allowed": False,
|
||||
"remote_write_performed": False,
|
||||
@@ -165,7 +263,12 @@ def build_windows99_vmx_source_locator_readback(
|
||||
"operation_boundaries": {
|
||||
"secret_value_read": False,
|
||||
"password_prompt_allowed": False,
|
||||
"file_content_read": False,
|
||||
"file_content_read": bool(
|
||||
receipt_applies and receipt.get("identity_metadata_read") is True
|
||||
),
|
||||
"bounded_identity_metadata_only": bool(
|
||||
receipt_applies and receipt.get("bounded_identity_metadata_only") is True
|
||||
),
|
||||
"raw_path_output": False,
|
||||
"remote_write_performed": False,
|
||||
"host_reboot_performed": False,
|
||||
@@ -177,7 +280,12 @@ def build_windows99_vmx_source_locator_readback(
|
||||
"allowed": locator_check_mode_ready,
|
||||
"effective_collect_ready": effective_locator_collect_ready,
|
||||
"path_existence_only": True,
|
||||
"vmx_file_content_read": False,
|
||||
"vmx_file_content_read": bool(
|
||||
receipt_applies and receipt.get("identity_metadata_read") is True
|
||||
),
|
||||
"bounded_identity_metadata_only": bool(
|
||||
receipt_applies and receipt.get("bounded_identity_metadata_only") is True
|
||||
),
|
||||
"raw_path_output": False,
|
||||
"path_fingerprint_only": True,
|
||||
"collector_command": safe_next_step if locator_check_mode_ready else "",
|
||||
|
||||
@@ -738,7 +738,7 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a
|
||||
"windows99_vmx_source_repair_playbook_trust_writeback_ref"
|
||||
].startswith("playbook://awoooi/windows99-vmx-source-repair/")
|
||||
assert state["windows99_vmx_source_locator_status"] == (
|
||||
"check_mode_locator_ready_windows99_vmx_source_required"
|
||||
"collector_readback_single_identity_candidate_confirmation_required"
|
||||
)
|
||||
assert state["windows99_vmx_source_locator_required"] is True
|
||||
assert state["windows99_vmx_source_locator_check_mode_ready"] is True
|
||||
@@ -752,12 +752,22 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a
|
||||
)
|
||||
assert state["windows99_vmx_source_locator_target_aliases"] == ["111"]
|
||||
assert state["windows99_vmx_source_locator_next_executable_step"] == (
|
||||
"restore_windows99_ssh_publickey_channel_then_rerun_locator"
|
||||
"confirm_single_unassigned_ubuntu_candidate_before_scoped_relink_dry_run"
|
||||
)
|
||||
assert state["windows99_vmx_source_locator_expected_vmx_path_count"] == 1
|
||||
assert state["windows99_vmx_source_locator_candidate_source_count_known"] is False
|
||||
assert state["windows99_vmx_source_locator_collector_readback_present"] is False
|
||||
assert state["windows99_vmx_source_locator_file_content_read"] is False
|
||||
assert state["windows99_vmx_source_locator_candidate_source_count"] == 6
|
||||
assert state["windows99_vmx_source_locator_alias_hint_candidate_count"] == 0
|
||||
assert state["windows99_vmx_source_locator_unassigned_ubuntu_candidate_count"] == 5
|
||||
assert (
|
||||
state[
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
]
|
||||
== 1
|
||||
)
|
||||
assert state["windows99_vmx_source_locator_candidate_confirmation_required"] is True
|
||||
assert state["windows99_vmx_source_locator_candidate_source_count_known"] is True
|
||||
assert state["windows99_vmx_source_locator_collector_readback_present"] is True
|
||||
assert state["windows99_vmx_source_locator_file_content_read"] is True
|
||||
assert state["windows99_vmx_source_locator_remote_write_performed"] is False
|
||||
assert state["windows99_vmx_source_locator_vm_power_change_performed"] is False
|
||||
assert payload["summary"]["controlled_service_data_backup_blocker_count"] == 0
|
||||
@@ -838,19 +848,32 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a
|
||||
"111"
|
||||
]
|
||||
assert payload["summary"]["windows99_vmx_source_locator_status"] == (
|
||||
"check_mode_locator_ready_windows99_vmx_source_required"
|
||||
"collector_readback_single_identity_candidate_confirmation_required"
|
||||
)
|
||||
assert payload["summary"]["windows99_vmx_source_locator_check_mode_ready"] is True
|
||||
assert payload["summary"]["windows99_vmx_source_locator_target_aliases"] == [
|
||||
"111"
|
||||
]
|
||||
assert payload["summary"]["windows99_vmx_source_locator_candidate_source_count"] == 6
|
||||
assert (
|
||||
payload["summary"][
|
||||
"windows99_vmx_source_locator_identity_unassigned_ubuntu_candidate_count"
|
||||
]
|
||||
== 1
|
||||
)
|
||||
assert (
|
||||
payload["summary"][
|
||||
"windows99_vmx_source_locator_candidate_confirmation_required"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
payload["rollups"]["windows99_vmx_source_locator_remote_write_performed"]
|
||||
is False
|
||||
)
|
||||
assert (
|
||||
payload["rollups"]["windows99_vmx_source_locator_file_content_read"]
|
||||
is False
|
||||
is True
|
||||
)
|
||||
assert "service/data/backup readback is green" in payload[
|
||||
"next_execution_order"
|
||||
@@ -902,7 +925,7 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a
|
||||
"windows99_vmx_source_repair_playbook_trust_writeback_ref"
|
||||
].startswith("playbook://awoooi/windows99-vmx-source-repair/")
|
||||
assert in_progress["evidence"]["windows99_vmx_source_locator_status"] == (
|
||||
"check_mode_locator_ready_windows99_vmx_source_required"
|
||||
"collector_readback_single_identity_candidate_confirmation_required"
|
||||
)
|
||||
assert (
|
||||
in_progress["evidence"]["windows99_vmx_source_locator_check_mode_ready"]
|
||||
@@ -912,6 +935,16 @@ def test_awoooi_priority_work_order_readback_routes_closed_backup_to_host_boot_a
|
||||
in_progress["evidence"]["windows99_vmx_source_locator_target_aliases"]
|
||||
== ["111"]
|
||||
)
|
||||
assert (
|
||||
in_progress["evidence"]["windows99_vmx_source_locator_candidate_source_count"]
|
||||
== 6
|
||||
)
|
||||
assert (
|
||||
in_progress["evidence"][
|
||||
"windows99_vmx_source_locator_candidate_confirmation_required"
|
||||
]
|
||||
is True
|
||||
)
|
||||
assert (
|
||||
in_progress["evidence"]["windows99_vmx_source_locator_remote_write_performed"]
|
||||
is False
|
||||
|
||||
@@ -56,6 +56,7 @@ def test_windows99_vmx_source_locator_builder_is_no_secret_check_mode() -> None:
|
||||
payload = build_windows99_vmx_source_locator_readback(
|
||||
_scorecard(),
|
||||
repair_package=repair_package,
|
||||
collector_receipt={},
|
||||
generated_at="2026-07-03T11:22:00+08:00",
|
||||
)
|
||||
|
||||
@@ -106,6 +107,69 @@ def test_windows99_vmx_source_locator_builder_is_no_secret_check_mode() -> None:
|
||||
assert payload["destructive_restore_allowed"] is False
|
||||
|
||||
|
||||
def test_windows99_vmx_source_locator_builder_projects_redacted_receipt() -> None:
|
||||
repair_package = build_windows99_vmx_source_repair_package(
|
||||
_scorecard(),
|
||||
generated_at="2026-07-03T11:21:00+08:00",
|
||||
)
|
||||
|
||||
payload = build_windows99_vmx_source_locator_readback(
|
||||
_scorecard(),
|
||||
repair_package=repair_package,
|
||||
collector_receipt={
|
||||
"schema_version": "windows99_vmx_source_locator_receipt_v1",
|
||||
"generated_at": "2026-07-03T12:41:34+08:00",
|
||||
"receipt_ref": "log://awoooi/p0-006/windows99-vmx-source-locator-111",
|
||||
"collector_readback_present": True,
|
||||
"collector_collection_status": (
|
||||
"collected_windows99_vmx_source_locator_stdout"
|
||||
),
|
||||
"target_host_alias": "99",
|
||||
"target_vm_aliases": ["111"],
|
||||
"expected_vmx_path_present_count": 0,
|
||||
"candidate_source_count": 6,
|
||||
"candidate_source_fingerprint_count": 0,
|
||||
"alias_hint_candidate_count": 0,
|
||||
"unassigned_ubuntu_candidate_count": 5,
|
||||
"identity_metadata_read": True,
|
||||
"bounded_identity_metadata_only": True,
|
||||
"identity_target_hint_count": 0,
|
||||
"identity_unassigned_ubuntu_candidate_count": 1,
|
||||
"locate_status": (
|
||||
"single_identity_unassigned_ubuntu_candidate_requires_confirmation"
|
||||
),
|
||||
"safe_next_step": (
|
||||
"confirm_single_unassigned_ubuntu_candidate_is_target_alias_before_scoped_relink_dry_run"
|
||||
),
|
||||
},
|
||||
generated_at="2026-07-03T12:42:00+08:00",
|
||||
)
|
||||
|
||||
assert payload["status"] == (
|
||||
"collector_readback_single_identity_candidate_confirmation_required"
|
||||
)
|
||||
assert payload["collector_readback_present"] is True
|
||||
assert payload["collector_collection_status"] == (
|
||||
"collected_windows99_vmx_source_locator_stdout"
|
||||
)
|
||||
assert payload["candidate_source_count_known"] is True
|
||||
assert payload["candidate_source_count"] == 6
|
||||
assert payload["alias_hint_candidate_count"] == 0
|
||||
assert payload["unassigned_ubuntu_candidate_count"] == 5
|
||||
assert payload["identity_metadata_read"] is True
|
||||
assert payload["bounded_identity_metadata_only"] is True
|
||||
assert payload["identity_target_hint_count"] == 0
|
||||
assert payload["identity_unassigned_ubuntu_candidate_count"] == 1
|
||||
assert payload["candidate_confirmation_required"] is True
|
||||
assert payload["next_executable_step"] == (
|
||||
"confirm_single_unassigned_ubuntu_candidate_before_scoped_relink_dry_run"
|
||||
)
|
||||
assert payload["raw_path_output"] is False
|
||||
assert payload["secret_value_read"] is False
|
||||
assert payload["remote_write_performed"] is False
|
||||
assert payload["vm_power_change_performed"] is False
|
||||
|
||||
|
||||
def test_windows99_vmx_source_locator_endpoint_returns_public_safe_readback(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
@@ -127,15 +191,22 @@ def test_windows99_vmx_source_locator_endpoint_returns_public_safe_readback(
|
||||
payload = response.json()
|
||||
assert payload["schema_version"] == "windows99_vmx_source_locator_readback_v1"
|
||||
assert payload["status"] == (
|
||||
"check_mode_locator_ready_windows99_vmx_source_required"
|
||||
"collector_readback_single_identity_candidate_confirmation_required"
|
||||
)
|
||||
assert payload["target_vm_aliases"] == ["111"]
|
||||
assert payload["locator_check_mode_ready"] is True
|
||||
assert payload["effective_locator_collect_ready"] is False
|
||||
assert payload["locator_collect_blocker"] == "ssh_batch_permission_denied"
|
||||
assert payload["collector_readback_present"] is True
|
||||
assert payload["candidate_source_count"] == 6
|
||||
assert payload["candidate_confirmation_required"] is True
|
||||
assert payload["public_lan_topology_redacted"] is True
|
||||
assert payload["raw_path_output"] is False
|
||||
assert payload["file_content_read"] is False
|
||||
assert payload["file_content_read"] is True
|
||||
assert payload["bounded_identity_metadata_only"] is True
|
||||
assert payload["remote_write_performed"] is False
|
||||
assert payload["vm_power_change_performed"] is False
|
||||
assert "192.168.0." not in response.text
|
||||
assert "D:\\" not in response.text
|
||||
assert "uuid." not in response.text
|
||||
assert "generatedAddress" not in response.text
|
||||
|
||||
Reference in New Issue
Block a user