from __future__ import annotations import json from pathlib import Path from jsonschema import Draft202012Validator, FormatChecker ROOT = Path(__file__).resolve().parents[1] RUNBOOK = ROOT / "docs" / "repository-rename-operations.md" HANDOFF_SCHEMA = ( ROOT / "docs" / "schemas" / "repository-rename-handoff-v1.schema.json" ) HANDOFF_EXAMPLE = ( ROOT / "docs" / "examples" / "repository-rename-handoff-v1.json" ) DASHBOARD_DOC = ROOT / "dashboard" / "src" / "docs" / "repository-renames.md" def test_repository_rename_handoff_example_validates_and_contains_no_secret_value(): schema = json.loads(HANDOFF_SCHEMA.read_text(encoding="utf-8")) example = json.loads(HANDOFF_EXAMPLE.read_text(encoding="utf-8")) Draft202012Validator.check_schema(schema) Draft202012Validator(schema, format_checker=FormatChecker()).validate(example) assert example["handoff_id"] == example["owning_work_record"]["task_id"] assert example["source_repository"] == example["owning_work_record"]["repository"] assert example["affected"]["paths"] or example["affected"]["graph_ids"] assert example["verification"] assert example["sensitive_data_prohibited"] is True serialized = json.dumps(example).lower() for forbidden in ( "bearer ", "basic ", "password=", "token=", "authorization=", "begin private key", "://user:", ): assert forbidden not in serialized def test_operator_runbook_names_phases_commands_owners_and_last_cleanup(): text = RUNBOOK.read_text(encoding="utf-8") for owner in ("State Hub", "Forgejo", "HelixForge/operator", "Target repository"): assert f"| {owner} |" in text for phase in ( "preflighted", "forge-renamed", "statehub-rebound", "source-synced", "consumers-verified", "completed", "rollback-preflight", "rolled-back", ): assert f"`{phase}`" in text for command in ( "statehub repo rename preflight", "statehub repo rename start", "statehub repo rename apply", "statehub repo rename status", "statehub repo rename verify", "statehub repo rename rollback", ): assert command in text assert "### Repository-only rename checklist" in text assert "### Product/runtime rename checklist" in text assert "## Dashboard interpretation" in text assert "## Recovery playbook" in text assert "## Rollback limits" in text assert "## Repository-boundary handoff format" in text assert "## Cleanup is deliberately last" in text assert "The old local checkout is the final removable asset" in text assert "The protected old slug alias is not cleanup material" in text assert "never parked only" in text assert "" in text def test_dashboard_reference_explains_alias_and_status_boundaries(): text = DASHBOARD_DOC.read_text(encoding="utf-8") assert "/repos/" in text assert "same repository UUID" in text assert "statehub repo rename status --json" in text assert "relationship checksums" in text assert "dashboard is a read surface" in text.lower() assert "old checkout is removed last" in text