4"""Mutation-sensitive source contracts for fleet reconciliation deployment."""
6from __future__
import annotations
12from pathlib
import Path
13from typing
import Protocol
15CAPACITY_LOCK_MODE = 0o660
19class InventoryModel(Protocol):
20 """Mutable inventory authority surface exercised by the selftest."""
25 def validate_runtime_inventory(self, state_dir: Path) ->
None:
26 """Validate one installed runtime inventory."""
29def _named_task_block(role_text: str, task_name: str) -> str:
30 """Return one Ansible task block at either top-level or block depth."""
31 lines = role_text.splitlines(keepends=
True)
33 index
for index, line
in enumerate(lines)
if line.lstrip() == f
"- name: {task_name}\n"
36 msg = f
"deployment role has no unique task named {task_name!r}"
39 indentation = len(lines[start]) - len(lines[start].lstrip())
41 for index
in range(start + 1, len(lines)):
43 same_depth = len(line) - len(line.lstrip()) == indentation
44 if same_depth
and line.lstrip().startswith(
"- name: "):
47 prefix =
" " * indentation
48 return "".join(line.removeprefix(prefix)
for line
in lines[start + 1 : end])
51def _deployment_uv_contract_errors(role_text: str) -> list[str]:
52 """Require candidate uv repair followed by a strictly read-only proof."""
53 errors: list[str] = []
55 check = _named_task_block(role_text,
"Prove the synchronized candidate Python environment")
56 sync = _named_task_block(role_text,
"Synchronize the candidate locked Python environment")
57 except ValueError
as error:
59 if "--run" not in check
or "--ensure-and-run" in check:
60 errors.append(
"candidate uv proof is not strictly read-only")
61 if "--ensure-and-run" not in sync:
62 errors.append(
"candidate uv repair cannot populate its authenticated cache")
66def _task(role: str, name: str, errors: list[str]) -> str:
67 """Return one required task and record its absence."""
69 return _named_task_block(role, name)
71 errors.append(f
"deployment task is missing: {name}")
75def _runtime_contract_errors(role: str) -> list[str]:
76 """Check independently converged private runtime paths."""
77 errors: list[str] = []
78 name =
"Converge private reconciliation runtime paths on every apply"
79 if role.splitlines().count(f
"- name: {name}") != 1:
80 errors.append(
"runtime convergence is missing or nested under source refresh")
81 converged = _task(role, name, errors)
82 inspected = _task(role,
"Inspect reconciliation runtime paths", errors)
83 paths = (
"ansible-local",
"dev_box_reconcile_state }}/control",
"ra8-fleet-mutation")
84 metadata = (
'owner: "{{ dev_box_user }}"',
'group: "{{ dev_box_user }}"',
'mode: "0700"')
85 if any(value
not in inspected
for value
in paths)
or any(
86 value
not in converged
for value
in metadata
88 errors.append(
"runtime paths are not independently private and exact")
92def _source_contract_errors(role: str) -> list[str]:
93 """Check installed source metadata and interrupted-swap recovery."""
94 errors: list[str] = []
95 auth = _task(role,
"Authenticate the installed reconciliation source metadata", errors)
97 "source_status.stat.isdir",
98 "source_status.stat.islnk",
99 "source_status.stat.uid",
100 "source_status.stat.gid",
101 "source_status.stat.mode",
102 "source_realpath.rc",
103 "source_realpath.stdout == dev_box_reconcile_source",
109 "marker_realpath.rc",
110 "marker_realpath.stdout",
111 "== dev_box_reconcile_source ~ '/.ra8-source-sha256'",
113 if any(value
not in auth
for value
in required):
114 errors.append(
"source-stale decision does not authenticate all root/marker metadata")
115 recovery = _task(role,
"Recover the sole last-good source before inspecting freshness", errors)
117 '[[ ! -e "$current" && ! -L "$current"',
118 '[[ -d "$previous" && ! -L "$previous" ]]',
119 'readlink -f -- "$previous"',
122 'mv -- "$previous" "$current"',
124 if any(value
not in recovery
for value
in proof):
125 errors.append(
"interrupted source swap recovery is incomplete")
129def _candidate_contract_errors(role: str) -> list[str]:
130 """Check candidate, systemd, activation, and retention order."""
132 "Create the reconciliation candidate root",
133 "Synchronize the candidate locked Python environment",
134 "Prove the synchronized candidate Python environment",
135 "Synchronize the candidate Galaxy collection set",
136 "Read the synchronized candidate Galaxy collection set",
137 "Prove the synchronized candidate Galaxy collection set",
138 "Prove the candidate reconciliation controller",
139 "Render the candidate reconciliation unit set",
140 "Validate the staged reconciliation unit set",
141 "Activate the fully proven reconciliation generation",
142 "Start reconciliation from the activated generation",
143 "Verify the activated reconciliation generation is scheduled",
144 "Retire recovery artifacts only after the timer is proven",
146 positions = [role.find(f
"- name: {name}\n")
for name
in names]
147 if any(position < 0
for position
in positions)
or positions != sorted(positions):
148 return [
"candidate proof, activation, or retention ordering is incomplete"]
152def _rollback_contract_errors(role: str) -> list[str]:
153 """Check isolated, authenticated, fail-closed last-good rollback."""
154 errors: list[str] = []
155 preserve = _task(role,
"Preserve each safe last-good unit", errors)
156 if "unit-previous" not in preserve
or "remote_src: true" not in preserve:
157 errors.append(
"safe last-good units are not retained before replacement")
158 switch = _task(role,
"Switch source while retaining exactly one recovery generation", errors)
160 "dev_box_reconcile_installed_safe",
161 'mv -- "$current" "$previous"',
162 'mv -- "$current" "$failed"',
164 if any(value
not in switch
for value
in switch_proof):
165 errors.append(
"unsafe current source is not isolated from last-good recovery")
166 restore = _task(role,
"Restore the exact last-good source after post-switch failure", errors)
168 '[[ -d "$previous" && ! -L "$previous" ]]',
169 'readlink -f -- "$previous"',
171 '[[ -f "$marker" && ! -L "$marker" ]]',
172 'readlink -f -- "$marker"',
175 'mv -- "$previous" "$current"',
177 if any(value
not in restore
for value
in restore_proof):
178 errors.append(
"last-good source rescue lacks complete authenticated metadata proof")
179 restart = _task(role,
"Restart the exact last-good reconciliation timer", errors)
182 for value
in (
"'restored' in",
"enabled: true",
"state: started",
"daemon_reload: true")
184 errors.append(
"last-good timer is not restarted only after authenticated rescue")
185 fail_closed = _task(role,
"Fail closed without an authenticated last-good generation", errors)
186 if "timer remains stopped" not in fail_closed:
187 errors.append(
"missing/tampered last-good does not leave the timer stopped")
191def _deployment_runtime_contract_errors(role: str) -> list[str]:
192 """Return all deployment authority errors."""
194 _runtime_contract_errors(role)
195 + _source_contract_errors(role)
196 + _candidate_contract_errors(role)
197 + _rollback_contract_errors(role)
202 role: str, mutations: tuple[tuple[str, str, str], ...], failures: list[str]
204 """Require each source mutation to trigger the contract checker."""
205 for old, new, label
in mutations:
206 if role.count(old) != 1:
207 failures.append(f
"deployment authority fixture is not unique: {label}")
208 elif not _deployment_runtime_contract_errors(role.replace(old, new, 1)):
209 failures.append(f
"deployment authority mutation stayed invisible: {label}")
212def _authority_mutations() -> tuple[tuple[str, str, str], ...]:
213 """Return runtime and installed-source mutations."""
216 "- name: Converge private reconciliation runtime paths on every apply\n",
217 " - name: Converge private reconciliation runtime paths on every apply\n",
220 (
"dev_box_reconcile_source_status.stat.uid",
"source_uid_removed",
"source uid"),
221 (
"dev_box_reconcile_source_status.stat.mode",
"source_mode_removed",
"source mode"),
222 (
"dev_box_reconcile_source_realpath.rc",
"source_realpath_removed",
"source realpath"),
223 (
"dev_box_reconcile_marker.stat.uid",
"marker_uid_removed",
"marker uid"),
224 (
"dev_box_reconcile_marker.stat.mode",
"marker_mode_removed",
"marker mode"),
225 (
"dev_box_reconcile_marker_realpath.rc",
"marker_realpath_removed",
"marker realpath"),
227 "- name: Recover the sole last-good source before inspecting freshness\n",
228 "- name: Recovery removed\n",
229 "interrupted recovery",
234def _candidate_rollback_mutations() -> tuple[tuple[str, str, str], ...]:
235 """Return candidate, systemd, retention, and fail-closed mutations."""
238 "- name: Synchronize the candidate locked Python environment\n",
239 "- name: Candidate uv removed\n",
243 "- name: Prove the synchronized candidate Galaxy collection set\n",
244 "- name: Candidate Galaxy proof removed\n",
248 "- name: Prove the candidate reconciliation controller\n",
249 "- name: Candidate controller proof removed\n",
250 "candidate controller",
253 "- name: Validate the staged reconciliation unit set\n",
254 "- name: Candidate unit proof removed\n",
258 "- name: Preserve each safe last-good unit\n",
259 "- name: Old units discarded\n",
260 "old unit retention",
263 "- name: Retire recovery artifacts only after the timer is proven\n",
264 "- name: Recovery artifacts retired early\n",
265 "old source retention",
268 "- name: Fail closed without an authenticated last-good generation\n",
269 "- name: Unsafe rollback allowed\n",
270 "no authenticated previous",
273 "- name: Restart the exact last-good reconciliation timer\n",
274 "- name: Rescue restart removed\n",
280def _check_unsafe_current(role: str, failures: list[str]) ->
None:
281 """Require unsafe current source to route to failed, never previous."""
282 move =
' mv -- "$current" "$failed"\n'
283 if role.count(move) != UNSAFE_MOVE_COUNT:
284 failures.append(
"unsafe-current isolation fixture count drifted")
286 weakened = role.replace(move,
' mv -- "$current" "$previous"\n', 1)
287 if not _deployment_runtime_contract_errors(weakened):
288 failures.append(
"unsafe current without previous stayed rollback-eligible")
291def _selftest_deployment_runtime_contract(repo_root: Path, failures: list[str]) ->
None:
292 """Prove deployment authority and every mutation direction."""
293 path = repo_root /
"infra/ansible/roles/dev_box/tasks/fleet_reconcile.yml"
294 role = path.read_text(encoding=
"ascii")
295 failures.extend(_deployment_runtime_contract_errors(role))
296 _check_mutations(role, _authority_mutations(), failures)
297 _check_mutations(role, _candidate_rollback_mutations(), failures)
298 _check_unsafe_current(role, failures)
301def _selftest_deployment_uv_contract(repo_root: Path, failures: list[str]) ->
None:
302 """Prove the candidate uv bootstrap works in both directions."""
303 role_path = repo_root /
"infra/ansible/roles/dev_box/tasks/fleet_reconcile.yml"
304 role_text = role_path.read_text(encoding=
"ascii")
305 failures.extend(_deployment_uv_contract_errors(role_text))
306 repair_weakened = role_text.replace(
"--ensure-and-run",
"--run", 1)
307 if not _deployment_uv_contract_errors(repair_weakened):
308 failures.append(
"candidate uv repair mutation stayed invisible")
309 check_start = role_text.index(
"- name: Prove the synchronized candidate Python environment")
310 check_weakened = role_text[:check_start] + role_text[check_start:].replace(
311 "--run",
"--ensure-and-run", 1
313 if not _deployment_uv_contract_errors(check_weakened):
314 failures.append(
"candidate uv check mutation stayed invisible")
317def _write_capacity_fixture(source: str, root: Path, state: Path) -> Path:
318 """Write one isolated capacity script and fake Docker implementation."""
319 script = root /
"capacity.sh"
320 old_state =
'RA8_FLEET_STATE_DIR="${RA8_FLEET_STATE_DIR:-/var/lib/ra8-fleet}"'
322 source.replace(old_state, f
'RA8_FLEET_STATE_DIR="{state}"'),
326 docker = root /
"docker"
330 'printf \'%s\\n\' "$*" >>"$RA8_TEST_DOCKER_LOG"\n'
332 " *\"ps -a\"*) printf 'runner\\n' ;;\n"
333 " *\"{{.State.Status}}\"*) printf 'exited\\n' ;;\n"
334 " *\"{{.Image}}\"*) printf 'sha256:test\\n' ;;\n"
335 ' *"run --rm"*) [ "${RA8_TEST_FAIL_ADMIT:-0}" = 0 ] ;;\n'
343def _capacity_environment(root: Path, commands: Path) -> dict[str, str]:
344 """Return a quiet-hours environment for the isolated capacity script."""
347 "PATH": f
"{root}:/usr/bin:/bin",
348 "RA8_TEST_DOCKER_LOG": str(commands),
349 "RA8_FLEET_DOCKER":
"docker",
350 "RA8_FLEET_STATE_GROUP": grp.getgrgid(os.getgid()).gr_name,
351 "RA8_FLEET_FULL_INSTANCES":
"1",
352 "RA8_FLEET_QUIET_INSTANCES":
"0",
353 "RA8_FLEET_QUIET_START":
"00:00",
354 "RA8_FLEET_QUIET_END":
"23:59",
355 "RA8_FLEET_QUIET_DAYS":
"Mon,Tue,Wed,Thu,Fri,Sat,Sun",
360 argv: list[str], environment: dict[str, str]
361) -> subprocess.CompletedProcess[bytes]:
362 """Run only the exact isolated capacity fixture assembled by this selftest."""
365 return subprocess.run(argv, env=environment, check=
False)
368def _capacity_runtime_selftest(repo_root: Path, failures: list[str]) ->
None:
369 """Exercise maintenance, timer exclusion, quiet restore, and retention."""
370 source_path = repo_root /
"scripts/ci/fleet_capacity.sh"
371 source = source_path.read_text(encoding=
"ascii")
372 with tempfile.TemporaryDirectory(prefix=
"ra8-capacity-selftest-")
as raw:
374 state = root /
"state"
375 state.mkdir(mode=0o770)
377 commands = root /
"docker.log"
378 script = _write_capacity_fixture(source, root, state)
379 environment = _capacity_environment(root, commands)
380 common = [str(script),
"--kind",
"docker",
"--container",
"runner"]
381 enter = _run_capacity([*common,
"maintenance-enter"], environment)
382 marker = state /
"maintenance"
383 lock = state /
"capacity.lock"
384 if enter.returncode
or not marker.is_file():
385 failures.append(
"maintenance entry did not durably park the host")
387 if not lock.is_file()
or lock.stat().st_mode & 0o777 != CAPACITY_LOCK_MODE:
388 failures.append(
"first controller did not create the shared capacity lock safely")
389 before = commands.read_text(encoding=
"ascii")
390 window = _run_capacity([*common,
"window"], environment)
391 after = commands.read_text(encoding=
"ascii")
392 if window.returncode
or not marker.is_file()
or " start " in after[len(before) :]:
393 failures.append(
"capacity timer admitted a host during maintenance")
394 restore = _run_capacity([*common,
"restore"], environment)
395 if restore.returncode
or marker.exists():
396 failures.append(
"quiet-hours restore did not clear maintenance")
397 quarantine = _run_capacity([*common,
"quarantine"], environment)
398 failed_environment = {
400 "RA8_FLEET_QUIET_DAYS":
"",
401 "RA8_TEST_FAIL_ADMIT":
"1",
403 failed = _run_capacity([*common,
"restore"], failed_environment)
404 if quarantine.returncode
or failed.returncode == 0
or not marker.is_file():
405 failures.append(
"failed restore did not retain durable quarantine")
406 bypass = _run_capacity([*common,
"scale",
"1"], environment)
407 if bypass.returncode == 0:
408 failures.append(
"caller-controlled scale bypassed durable maintenance")
411def _capacity_k8s_missing_selftest(repo_root: Path, failures: list[str]) ->
None:
412 """Prove only exact missing-ARS maintenance entry is accepted as parked."""
413 source = (repo_root /
"scripts/ci/fleet_capacity.sh").read_text(encoding=
"ascii")
414 with tempfile.TemporaryDirectory(prefix=
"ra8-capacity-k8s-")
as raw:
416 state = root /
"state"
417 state.mkdir(mode=0o770)
419 script = _write_capacity_fixture(source, root, state)
420 kubectl = root /
"kubectl"
423 'if [ "${RA8_TEST_K8S_ERROR:-}" = notfound ]; then\n'
424 " printf '%s\n' 'Error from server (NotFound): "
425 'autoscalingrunnersets.actions.github.com "ra8-ci" not found\' >&2\n'
428 "printf '%s\n' 'Unable to connect to the server: refused' >&2\n"
435 "PATH": f
"{root}:/usr/bin:/bin",
436 "RA8_FLEET_STATE_GROUP": grp.getgrgid(os.getgid()).gr_name,
437 "RA8_FLEET_KUBECTL": str(kubectl),
438 "RA8_FLEET_FULL_INSTANCES":
"1",
439 "RA8_TEST_K8S_ERROR":
"notfound",
441 common = [str(script),
"--kind",
"k8s",
"--scale-set",
"ra8-ci"]
442 enter = _run_capacity([*common,
"maintenance-enter"], environment)
443 if enter.returncode
or not (state /
"maintenance").is_file():
444 failures.append(
"exact missing ARC scale set did not enter maintenance")
445 quarantine = _run_capacity([*common,
"quarantine"], environment)
446 if quarantine.returncode == 0:
447 failures.append(
"missing ARC scale set was accepted outside maintenance entry")
448 other = _run_capacity(
449 [*common,
"maintenance-enter"],
450 {**environment,
"RA8_TEST_K8S_ERROR":
"transport"},
452 if other.returncode == 0:
453 failures.append(
"non-NotFound kubectl failure was accepted as zero admission")
456def _source_contract_selftest(repo_root: Path, failures: list[str]) ->
None:
457 """Require parked roles, candidate rollback, and read-only WSL checks."""
459 "fleet": repo_root /
"scripts/dev/fleet.py",
460 "wsl": repo_root /
"scripts/dev/fleet_wsl.py",
461 "stage": repo_root /
"scripts/dev/fleet_wsl_stage.py",
462 "docker": repo_root /
"infra/ansible/roles/ci_runner_docker/tasks/deploy.yml",
463 "arc": repo_root /
"infra/ansible/roles/ci_runner/tasks/main.yml",
464 "role": repo_root /
"infra/ansible/roles/dev_box/tasks/fleet_reconcile.yml",
465 "capacity-role": repo_root /
"infra/ansible/roles/fleet_capacity/tasks/main.yml",
466 "arc-play": repo_root /
"infra/ansible/playbooks/ci-runner.yml",
468 texts = {name: path.read_text(encoding=
"ascii")
for name, path
in paths.items()}
470 (
"fleet",
'["-e", "fleet_reconcile_parked=true"]', 1),
471 (
"fleet",
'["maintenance-enter"]', 1),
472 (
"docker",
"if fleet_reconcile_parked | default(false) | bool", 1),
473 (
"arc",
"{{ 0 if fleet_reconcile_parked", 2),
474 (
"fleet",
"fleet_reconcile_activation_hold=true", 1),
475 (
"arc",
"post_renderer: >-", 1),
476 (
"arc",
'spec["maxRunners"] = 0', 1),
477 (
"arc",
"if matches != 1:", 1),
478 (
"stage",
'mode == "apply" and not installed else "--verify-cache"', 1),
479 (
"wsl",
'if spec.mode == "check":', 3),
480 (
"wsl",
'fws.transaction_lock_lines(spec.mode != "check")', 1),
481 (
"fleet",
'sync_image=request.args.mode == "apply"', 1),
482 (
"capacity-role",
'path: "{{ fleet_capacity_state_dir }}/capacity.lock"', 1),
483 (
"capacity-role",
'group: "{{ fleet_capacity_state_group }}"', 2),
484 (
"capacity-role",
'mode: "0660"', 1),
485 (
"arc-play",
" - fleet_capacity\n", 1),
487 for name, value, expected
in required:
488 if texts[name].count(value) != expected:
489 failures.append(
"parked role or WSL read-only contract count drifted")
490 weakened = texts[name].replace(value,
"", 1)
491 if weakened.count(value) == expected:
492 failures.append(
"source contract mutation unexpectedly stayed invisible")
495def runtime_inventory_selftest(model: InventoryModel) -> list[str]:
496 """Prove installed inventory and host variables share one exact authority."""
497 failures: list[str] = []
498 original = model.INVENTORY
499 with tempfile.TemporaryDirectory(prefix=
"ra8-runtime-inventory-")
as raw:
500 state_dir = Path(raw)
501 inventory_dir = state_dir /
"inventory"
502 inventory_dir.mkdir()
503 model.INVENTORY = inventory_dir /
"hosts.ini"
504 host_vars = inventory_dir /
"host_vars"
505 host_vars.symlink_to(model.HOST_VARS_DIR)
507 model.validate_runtime_inventory(state_dir)
509 host_vars.symlink_to(state_dir)
511 model.validate_runtime_inventory(state_dir)
512 failures.append(
"runtime inventory accepted a foreign host-vars authority")
516 model.INVENTORY = original
520def run(repo_root: Path) -> list[str]:
521 """Return deployment contract failures for the injected repository root."""
522 failures: list[str] = []
523 _selftest_deployment_runtime_contract(repo_root, failures)
524 _selftest_deployment_uv_contract(repo_root, failures)
525 _capacity_runtime_selftest(repo_root, failures)
526 _capacity_k8s_missing_selftest(repo_root, failures)
527 _source_contract_selftest(repo_root, failures)