3"""Own and publish the WSL fleet's staged control bytes without path races."""
5from __future__
import annotations
17from collections.abc
import Callable
18from pathlib
import Path
21import fleet_model
as fm
22import fleet_reach
as fr
23import fleet_runner_maintenance
as frm
25WSL_STAGE =
"/opt/ra8-infra"
28WSL_RUNNER_IMAGE_CACHE =
"/opt/ra8-infra-cache/ra8-ci-runner.tar"
29STAGE_OWNER =
"ra8-firmware fleet WSL stage v1"
30CACHE_OWNER =
"ra8-firmware fleet WSL runner cache v1"
31OWNER_FILE =
".ra8-fleet-owner"
32GENERATION_FILE =
".ra8-stage-generation"
33REMOTE_APPLY_REQUIRED_STATUS = 42
34STAGE_DIRECTORY_MEMBERS = (
35 ".ansible/collections",
40 *STAGE_DIRECTORY_MEMBERS,
42 "scripts/checks/check_ansible_collections.py",
43 "scripts/ci/fleet_capacity.sh",
44 "scripts/dev/bootstrap_uv.py",
45 "scripts/dev/bootstrap_uv_exec.py",
46 "scripts/dev/fleet_runner_maintenance.py",
47 "scripts/dev/fleet_path_authority.py",
48 "scripts/dev/uv_release.json",
49 "scripts/dev/verify_locked_environment.py",
53CommandRunner = Callable[..., int]
56def _fail(message: str) -> int:
57 """Print one transport failure and return the fleet precondition status."""
58 print(f
"fleet: error: {message}", file=sys.stderr)
62def _bootstrap_environment() -> dict[str, str]:
63 """Return a local uv bootstrap environment without inherited controls."""
65 "HOME": pwd.getpwuid(os.getuid()).pw_dir,
68 "PATH":
"/usr/bin:/bin",
70 clean[
"PYTHONNOUSERSITE"] =
"1"
74def _links_stay_within(root: Path) -> bool:
75 """Accept only existing relative links whose targets stay below ``root``."""
76 authority = root.resolve(strict=
True)
77 for entry
in root.rglob(
"*"):
78 if not entry.is_symlink():
81 target = entry.resolve(strict=
True)
82 except (OSError, RuntimeError):
84 if entry.readlink().is_absolute()
or not target.is_relative_to(authority):
89def _installed_snapshot() -> bool:
90 """Return whether this source is the root-owned immutable service snapshot."""
91 marker = fm.REPO_ROOT /
".ra8-source-sha256"
93 root_metadata = fm.REPO_ROOT.lstat()
94 metadata = marker.lstat()
95 digest = marker.read_text(encoding=
"ascii").strip()
99 not fm.REPO_ROOT.is_symlink()
100 and root_metadata.st_uid == 0
101 and stat.S_ISREG(metadata.st_mode)
102 and not marker.is_symlink()
103 and metadata.st_uid == 0
104 and stat.S_IMODE(metadata.st_mode) == ROOT_READ_MODE
105 and len(digest) == SHA256_HEX_LENGTH
106 and all(character
in "0123456789abcdef" for character
in digest)
110def _bootstrap_action(mode: str, installed: bool) -> str:
111 """Select mutation only for an operator-owned apply checkout."""
112 return "--ensure" if mode ==
"apply" and not installed
else "--verify-cache"
115def verify_stage_sources(mode: str) -> int:
116 """Authenticate local staged authorities before any remote side effect."""
118 frm.ansible_environment(os.environ, fm.ANSIBLE_DIR)
119 except frm.MaintenanceError
as exc:
120 return _fail(str(exc))
121 bootstrap = fm.REPO_ROOT /
"scripts/dev/bootstrap_uv.py"
122 action = _bootstrap_action(mode, _installed_snapshot())
123 result = subprocess.run(
124 [sys.executable, str(bootstrap), action],
126 env=_bootstrap_environment(),
132 if result.returncode:
133 sys.stderr.write(result.stderr)
134 return _fail(
"pinned uv cache is unavailable for the WSL stage")
135 for relative
in STAGE_MEMBERS:
136 path = fm.REPO_ROOT / relative
137 if not path.exists()
or path.is_symlink():
138 return _fail(f
"WSL stage authority is absent or linked: {relative}")
139 if path.is_dir()
and not _links_stay_within(path):
140 return _fail(f
"WSL stage authority contains an escaping link: {relative}")
144def _generation_records(root: Path) -> list[tuple[str, str, int, str]]:
145 """Describe every staged path by name, type, mode, and authenticated payload."""
146 records: list[tuple[str, str, int, str]] = []
147 for member
in STAGE_MEMBERS:
148 start = root / member
151 paths.extend(sorted(start.rglob(
"*"), key=
lambda path: path.as_posix()))
153 metadata = path.lstat()
154 relative = path.relative_to(root).as_posix()
155 mode = stat.S_IMODE(metadata.st_mode)
156 if path.is_symlink():
157 records.append((relative,
"l", mode, str(path.readlink())))
159 records.append((relative,
"d", mode,
""))
161 digest = hashlib.sha256(path.read_bytes()).hexdigest()
162 records.append((relative,
"f", mode, digest))
164 msg = f
"unsupported WSL stage authority type: {relative}"
165 raise ValueError(msg)
169def stage_generation(root: Path = fm.REPO_ROOT) -> str:
170 """Return the canonical complete-generation digest for staged authorities."""
171 encoded = json.dumps(_generation_records(root), separators=(
",",
":")).encode(
"ascii")
172 return hashlib.sha256(encoded).hexdigest()
175def _generation_probe_command(root: str) -> str:
176 """Render a read-only complete-generation digest probe for the remote stage."""
177 code =
"""import hashlib,json,os,stat,sys
178from pathlib import Path
179root=Path(sys.argv[1])
180members=json.loads(sys.argv[2])
182for member in members:
186 paths.extend(sorted(start.rglob("*"),key=lambda path:path.as_posix()))
188 metadata=path.lstat()
189 relative=path.relative_to(root).as_posix()
190 mode=stat.S_IMODE(metadata.st_mode)
191 if path.is_symlink():
192 records.append((relative,"l",mode,os.readlink(path)))
194 records.append((relative,"d",mode,""))
196 records.append((relative,"f",mode,hashlib.sha256(path.read_bytes()).hexdigest()))
198 raise SystemExit("unsupported staged path type: "+relative)
199print(hashlib.sha256(json.dumps(records,separators=(",",":")).encode("ascii")).hexdigest())
201 members = json.dumps(STAGE_MEMBERS)
203 f
"/usr/bin/python3 -I -S -c {shlex.quote(code)} {shlex.quote(root)} {shlex.quote(members)}"
207def _stage_archive(mode: str) -> tuple[int, bytes]:
208 """Build one authenticated local archive before touching the remote stage."""
209 rc = verify_stage_sources(mode)
212 tar_tool = Path(
"/usr/bin/tar")
213 if not tar_tool.is_file()
or tar_tool.is_symlink()
or not os.access(tar_tool, os.X_OK):
214 return _fail(
"trusted /usr/bin/tar is unavailable"), b
""
215 tar = subprocess.run(
229 sys.stderr.write(tar.stderr.decode(
"utf-8",
"replace"))
230 return tar.returncode, tar.stdout
233def _owned_shell(owner: str, owner_uid: int = 0) -> list[str]:
234 """Render reusable exact-owner and no-mount directory operations."""
236 f
"expected_owner={shlex.quote(owner)}",
237 f
"expected_owner_uid={owner_uid}",
239 ' [ -d "$1" ] && [ ! -L "$1" ] && ! /usr/bin/mountpoint -q -- "$1" &&',
240 ' [ "$(stat -c %u -- "$1")" = "$expected_owner_uid" ] &&',
241 ' [ "$(stat -c %a -- "$1")" = 755 ] &&',
242 f
' [ -f "$1/{OWNER_FILE}" ] && [ ! -L "$1/{OWNER_FILE}" ] &&',
243 f
' [ "$(stat -c %u -- "$1/{OWNER_FILE}")" = "$expected_owner_uid" ] &&',
244 f
' [ "$(stat -c %a -- "$1/{OWNER_FILE}")" = 644 ] &&',
245 f
' [ "$(cat -- "$1/{OWNER_FILE}")" = "$expected_owner" ]',
248 " /usr/bin/python3 -I -S -c 'import os,sys; "
249 "f=os.open(sys.argv[1],os.O_RDONLY|os.O_NOFOLLOW); "
250 'os.fsync(f); os.close(f)\' "$1"',
253 " /usr/bin/python3 -I -S -c 'import os,sys; "
254 "f=os.open(sys.argv[1],os.O_RDONLY|os.O_DIRECTORY); "
255 'os.fsync(f); os.close(f)\' "$1"',
257 "remove_owned_dir() {",
258 ' owned_dir "$1" || { echo "refusing unowned WSL path: $1" >&2; exit 1; }',
259 ' parent="$(dirname -- "$1")"',
260 ' rm -rf --one-file-system -- "$1"',
261 ' sync_dir "$parent"',
266def transaction_lock_lines(
267 exclusive: bool, lock_root: str =
"/run/lock", owner_uid: int = 0
269 """Render a no-write host-local reader or writer lock acquisition."""
270 option =
"-x" if exclusive
else "-s"
272 f
"lock_root={shlex.quote(lock_root)}",
273 '[ -d "$lock_root" ] && [ ! -L "$lock_root" ] &&',
274 ' [ "$(readlink -f -- "$lock_root")" = "$lock_root" ] &&',
275 f
' [ "$(stat -c %u -- "$lock_root")" = {owner_uid} ] || {{',
276 ' echo "unsafe WSL lock authority" >&2; exit 1;',
278 'case "$(stat -c %a -- "$lock_root")" in 755|775|1777) ;;',
279 ' *) echo "unsafe WSL lock authority mode" >&2; exit 1 ;;',
281 'exec 9<"$lock_root"',
282 f
"/usr/bin/flock {option} 9",
286def stage_probe_lines(expected: str, stage: str = WSL_STAGE) -> list[str]:
287 """Render authenticated read-only classification of one installed generation."""
288 marker = f
"{stage}/{GENERATION_FILE}"
289 probe = _generation_probe_command(stage)
291 f
"stage={shlex.quote(stage)}",
292 f
"generation_marker={shlex.quote(marker)}",
293 'if [ ! -e "$stage" ] && [ ! -L "$stage" ]; then',
294 f
' echo "WSL stage is missing; apply required" >&2; exit {REMOTE_APPLY_REQUIRED_STATUS}',
296 *_owned_shell(STAGE_OWNER, 0
if stage == WSL_STAGE
else os.getuid()),
297 'owned_dir "$stage" || { echo "unsafe WSL stage authority" >&2; exit 1; }',
298 'if [ ! -e "$generation_marker" ] && [ ! -L "$generation_marker" ]; then',
299 f
' echo "WSL generation manifest is missing; apply required" >&2; '
300 f
"exit {REMOTE_APPLY_REQUIRED_STATUS}",
302 '[ -f "$generation_marker" ] && [ ! -L "$generation_marker" ] &&',
303 ' [ "$(stat -c %u -- "$generation_marker")" = "$expected_owner_uid" ] &&',
304 ' [ "$(stat -c %a -- "$generation_marker")" = 444 ] || {',
305 ' echo "unsafe WSL generation manifest" >&2; exit 1;',
307 'installed_generation="$(cat -- "$generation_marker")"',
308 f
'if [ "$installed_generation" != {shlex.quote(expected)} ]; then',
309 f
' echo "WSL stage is stale; apply required" >&2; exit {REMOTE_APPLY_REQUIRED_STATUS}',
311 f
'actual_generation="$({probe})" || {{',
312 ' echo "could not authenticate WSL stage generation" >&2; exit 1;',
314 '[ "$actual_generation" = "$installed_generation" ] || {',
315 ' echo "WSL stage generation authentication failed" >&2; exit 1;',
320def stage_prepare_script(stage: str = WSL_STAGE) -> str:
321 """Render deterministic recovery and fresh incoming-stage creation."""
322 incoming = f
"{stage}.incoming"
323 previous = f
"{stage}.previous"
324 owner_uid = 0
if stage == WSL_STAGE
else os.getuid()
325 lines = [
"set -euo pipefail", *_owned_shell(STAGE_OWNER, owner_uid)]
328 f
"stage={shlex.quote(stage)}",
329 f
"incoming={shlex.quote(incoming)}",
330 f
"previous={shlex.quote(previous)}",
331 'if [ -e "$previous" ] || [ -L "$previous" ]; then',
332 ' owned_dir "$previous" || { echo "unowned previous WSL stage" >&2; exit 1; }',
333 ' if [ -e "$stage" ] || [ -L "$stage" ]; then',
334 ' owned_dir "$stage" || { echo "unowned current WSL stage" >&2; exit 1; }',
335 ' remove_owned_dir "$previous"',
337 ' mv -- "$previous" "$stage"',
338 ' sync_dir "$(dirname -- "$stage")"',
341 'if [ -e "$stage" ] || [ -L "$stage" ]; then',
342 ' owned_dir "$stage" || { echo "refusing unowned WSL stage" >&2; exit 1; }',
344 'if [ -e "$incoming" ] || [ -L "$incoming" ]; then',
345 ' remove_owned_dir "$incoming"',
347 'install -d -m 0755 -- "$incoming"',
348 f
'printf \'%s\\n\' "$expected_owner" >"$incoming/{OWNER_FILE}"',
349 f
'chmod 0644 "$incoming/{OWNER_FILE}"',
350 f
'sync_file "$incoming/{OWNER_FILE}"',
351 'sync_dir "$incoming"',
352 'sync_dir "$(dirname -- "$incoming")"',
355 return "\n".join(lines) +
"\n"
358def stage_seal_script(generation: str, stage: str = WSL_STAGE) -> str:
359 """Authenticate an incoming generation and durably seal its manifest."""
360 incoming = f
"{stage}.incoming"
361 marker = f
"{incoming}/{GENERATION_FILE}"
362 probe = _generation_probe_command(incoming)
366 *_owned_shell(STAGE_OWNER, 0
if stage == WSL_STAGE
else os.getuid()),
367 f
"incoming={shlex.quote(incoming)}",
368 'owned_dir "$incoming" || { echo "incoming WSL stage is not owned" >&2; exit 1; }',
369 f
'actual_generation="$({probe})"',
370 f
'[ "$actual_generation" = {shlex.quote(generation)} ] || {{',
371 ' echo "incoming WSL stage generation mismatch" >&2; exit 1;',
373 f
"printf '%s\\n' {shlex.quote(generation)} >{shlex.quote(marker)}",
374 f
"chmod 0444 {shlex.quote(marker)}",
375 f
"sync_file {shlex.quote(marker)}",
376 'sync_dir "$incoming"',
382def stage_publish_script(stage: str = WSL_STAGE, generation: str |
None =
None) -> str:
383 """Render atomic stage publication with deterministic rollback."""
384 incoming = f
"{stage}.incoming"
385 previous = f
"{stage}.previous"
386 generation = generation
or ""
387 owner_uid = 0
if stage == WSL_STAGE
else os.getuid()
388 lines = [
"set -euo pipefail", *_owned_shell(STAGE_OWNER, owner_uid)]
391 f
"stage={shlex.quote(stage)}",
392 f
"incoming={shlex.quote(incoming)}",
393 f
"previous={shlex.quote(previous)}",
394 'owned_dir "$incoming" || { echo "incoming WSL stage is not owned" >&2; exit 1; }',
395 f
"generation_marker={shlex.quote(incoming + '/' + GENERATION_FILE)}",
396 '[ -f "$generation_marker" ] && [ ! -L "$generation_marker" ] &&',
397 ' [ "$(stat -c %u -- "$generation_marker")" = "$expected_owner_uid" ] &&',
398 ' [ "$(stat -c %a -- "$generation_marker")" = 444 ] || {',
399 ' echo "incoming WSL generation manifest is unsafe" >&2; exit 1;',
403 f
'[ "$(cat -- "$generation_marker")" = {shlex.quote(generation)} ] || {{',
404 ' echo "incoming WSL generation manifest is stale" >&2; exit 1;',
410 '[ ! -e "$previous" ] && [ ! -L "$previous" ] || {',
411 ' echo "previous WSL stage was not recovered" >&2; exit 1;',
413 'if [ -e "$stage" ] || [ -L "$stage" ]; then',
414 ' owned_dir "$stage" || { echo "refusing unowned WSL stage" >&2; exit 1; }',
415 ' mv -- "$stage" "$previous"',
416 ' sync_dir "$(dirname -- "$stage")"',
418 'if ! mv -- "$incoming" "$stage"; then',
419 ' [ ! -e "$previous" ] || mv -- "$previous" "$stage"',
420 ' sync_dir "$(dirname -- "$stage")"',
423 'sync_dir "$(dirname -- "$stage")"',
424 'if [ -e "$previous" ]; then remove_owned_dir "$previous"; fi',
427 return "\n".join(lines) +
"\n"
430def stage_cleanup_script(stage: str = WSL_STAGE) -> str:
431 """Render cleanup limited to the exact owned incoming directory."""
432 incoming = f
"{stage}.incoming"
436 *_owned_shell(STAGE_OWNER, 0
if stage == WSL_STAGE
else os.getuid()),
437 f
"incoming={shlex.quote(incoming)}",
438 'if [ -e "$incoming" ] || [ -L "$incoming" ]; then',
439 ' remove_owned_dir "$incoming"',
446def prepare(data: dict[str, Any], name: str, mode: str, run: CommandRunner) -> tuple[int, str]:
447 """Transfer and authenticate an incoming generation without publishing it."""
448 tar_rc, archive = _stage_archive(mode)
451 generation = stage_generation()
452 host = data[
"hosts"][name]
453 ssh = fr.ssh_target(data, name)
454 shell = fm.remote_shell(host)
455 rc = run([*ssh, shell], stdin=stage_prepare_script())
458 distro = str(host[
"connect"][
"distro"])
459 incoming = f
"{WSL_STAGE}.incoming"
461 f
"wsl -d {shlex.quote(distro)} -u root -e /usr/bin/env -i "
462 f
"HOME=/root PATH=/usr/bin:/bin /usr/bin/tar -xzf - -C {shlex.quote(incoming)}"
464 rc = run([*ssh, unpack], stdin=archive)
466 rc = run([*ssh, shell], stdin=stage_seal_script(generation))
468 run([*ssh, shell], stdin=stage_cleanup_script())
473def push(data: dict[str, Any], name: str, mode: str, run: CommandRunner) -> int:
474 """Atomically publish authenticated control inputs to the WSL distro."""
475 rc, generation = prepare(data, name, mode, run)
478 host = data[
"hosts"][name]
479 ssh = fr.ssh_target(data, name)
480 shell = fm.remote_shell(host)
484 *transaction_lock_lines(exclusive=
True),
485 stage_publish_script(generation=generation),
488 rc = run([*ssh, shell], stdin=script)
490 run([*ssh, shell], stdin=stage_cleanup_script())
494def cache_prepare_script(cache: str = WSL_RUNNER_IMAGE_CACHE) -> str:
495 """Render exact cache ownership and no-follow staging preparation."""
496 root = str(Path(cache).parent)
497 part = f
"{cache}.part"
498 owner_uid = 0
if cache == WSL_RUNNER_IMAGE_CACHE
else os.getuid()
499 lines = [
"set -euo pipefail", *_owned_shell(CACHE_OWNER, owner_uid)]
502 f
"cache_root={shlex.quote(root)}",
503 f
"dest={shlex.quote(cache)}",
504 f
"part={shlex.quote(part)}",
505 'if [ -e "$cache_root" ] || [ -L "$cache_root" ]; then',
506 ' owned_dir "$cache_root" || { echo "refusing unowned runner cache" >&2; exit 1; }',
508 ' install -d -m 0755 -- "$cache_root"',
509 f
' printf \'%s\\n\' "$expected_owner" >"$cache_root/{OWNER_FILE}"',
510 f
' chmod 0644 "$cache_root/{OWNER_FILE}"',
511 f
' sync_file "$cache_root/{OWNER_FILE}"',
512 ' sync_dir "$cache_root"',
513 ' sync_dir "$(dirname -- "$cache_root")"',
515 'for path in "$dest" "$part"; do',
516 ' if [ -e "$path" ] || [ -L "$path" ]; then',
517 ' [ -f "$path" ] && [ ! -L "$path" ] && ! /usr/bin/mountpoint -q -- "$path" || {',
518 ' echo "refusing linked or non-file runner cache path: $path" >&2; exit 1;',
522 'if [ -e "$part" ]; then',
524 ' sync_dir "$cache_root"',
528 return "\n".join(lines) +
"\n"
531def cache_receive_command(distro: str, cache: str = WSL_RUNNER_IMAGE_CACHE) -> str:
532 """Return a Windows-shell-safe exclusive runner-image receiver."""
533 part = f
"{cache}.part"
544 "PATH=/usr/bin:/bin",
551 safe =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/._,:=+-"
552 if any(
not token
or any(character
not in safe
for character
in token)
for token
in tokens):
553 message =
"runner-image receiver cannot be represented safely for Windows"
554 raise ValueError(message)
555 return " ".join(tokens)
558def cache_cleanup_script(cache: str = WSL_RUNNER_IMAGE_CACHE) -> str:
559 """Remove only a regular part file below an exact owned cache root."""
560 root = str(Path(cache).parent)
561 part = f
"{cache}.part"
565 *_owned_shell(CACHE_OWNER, 0
if cache == WSL_RUNNER_IMAGE_CACHE
else os.getuid()),
566 f
"cache_root={shlex.quote(root)}",
567 f
"part={shlex.quote(part)}",
568 'owned_dir "$cache_root" || { echo "runner cache ownership lost" >&2; exit 1; }',
569 'if [ -e "$part" ] || [ -L "$part" ]; then',
570 ' [ -f "$part" ] && [ ! -L "$part" ] || { exit 1; }',
572 ' sync_dir "$cache_root"',
579def cache_publish_script(source_sha: str, cache: str = WSL_RUNNER_IMAGE_CACHE) -> str:
580 """Authenticate and atomically publish an owned runner-image part."""
581 root = str(Path(cache).parent)
582 part = f
"{cache}.part"
583 owner_uid = 0
if cache == WSL_RUNNER_IMAGE_CACHE
else os.getuid()
584 lines = [
"set -euo pipefail", *_owned_shell(CACHE_OWNER, owner_uid)]
587 f
"cache_root={shlex.quote(root)}",
588 f
"dest={shlex.quote(cache)}",
589 f
"part={shlex.quote(part)}",
590 'owned_dir "$cache_root" || { echo "runner cache ownership lost" >&2; exit 1; }',
591 '[ -f "$part" ] && [ ! -L "$part" ] || { echo "runner cache part lost" >&2; exit 1; }',
592 'if [ -e "$dest" ] || [ -L "$dest" ]; then',
593 ' [ -f "$dest" ] && [ ! -L "$dest" ] || {',
594 ' echo "runner cache dest unsafe" >&2; exit 1;',
597 'actual=$(sha256sum -- "$part")',
598 "actual=${actual%% *}",
599 f
'if [ "$actual" != {shlex.quote(source_sha)} ]; then',
600 ' echo "runner image checksum mismatch" >&2',
603 'chmod 0644 "$part"',
605 'mv -f -- "$part" "$dest"',
606 'sync_dir "$cache_root"',
609 return "\n".join(lines) +
"\n"
612def _run_shell(script: str) -> subprocess.CompletedProcess[str]:
613 """Run one offline transaction selftest shell."""
614 return subprocess.run([
"/bin/bash"], input=script, text=
True, capture_output=
True, check=
False)
617def _write_owner(path: Path, owner: str) ->
None:
618 """Create one fixture-owned directory and exact marker."""
619 path.mkdir(parents=
True)
620 (path / OWNER_FILE).write_text(f
"{owner}\n", encoding=
"ascii")
623def _stage_selftest(root: Path) -> list[str]:
624 """Prove unowned preservation, transfer cleanup, and atomic replacement."""
625 failures: list[str] = []
626 stage = root /
"stage"
628 sentinel = stage /
"preserve"
629 sentinel.write_text(
"unowned\n", encoding=
"ascii")
630 if _run_shell(stage_prepare_script(str(stage))).returncode == 0
or not sentinel.exists():
631 failures.append(
"unowned WSL stage was replaced")
633 _write_owner(stage, STAGE_OWNER)
634 sentinel = stage /
"last-good"
635 sentinel.write_text(
"keep\n", encoding=
"ascii")
636 if _run_shell(stage_prepare_script(str(stage))).returncode:
637 failures.append(
"owned WSL stage preparation failed")
639 incoming = Path(f
"{stage}.incoming")
640 (incoming /
"partial").write_text(
"partial\n", encoding=
"ascii")
641 if _run_shell(stage_cleanup_script(str(stage))).returncode
or not sentinel.exists():
642 failures.append(
"failed transfer did not preserve the last-good WSL stage")
643 if _run_shell(stage_prepare_script(str(stage))).returncode:
644 failures.append(
"second owned WSL stage preparation failed")
646 incoming = Path(f
"{stage}.incoming")
647 (incoming /
"new").write_text(
"new\n", encoding=
"ascii")
648 generation =
"a" * SHA256_HEX_LENGTH
649 marker = incoming / GENERATION_FILE
650 marker.write_text(f
"{generation}\n", encoding=
"ascii")
651 marker.chmod(ROOT_READ_MODE)
653 _run_shell(stage_publish_script(str(stage), generation)).returncode
654 or not (stage /
"new").is_file()
656 failures.append(
"owned WSL stage did not publish atomically")
657 previous = Path(f
"{stage}.previous")
658 stage.rename(previous)
659 if _run_shell(stage_prepare_script(str(stage))).returncode
or not (stage /
"new").is_file():
660 failures.append(
"interrupted WSL publication did not recover the last-good generation")
661 _run_shell(stage_cleanup_script(str(stage)))
665def _cache_selftest(root: Path) -> list[str]:
666 """Prove unowned cache and planted-part links are preserved/refused."""
667 failures: list[str] = []
668 cache_root = root /
"cache"
669 cache = cache_root /
"runner.tar"
671 sentinel = cache_root /
"preserve"
672 sentinel.write_text(
"unowned\n", encoding=
"ascii")
673 if _run_shell(cache_prepare_script(str(cache))).returncode == 0
or not sentinel.exists():
674 failures.append(
"unowned runner cache was claimed or removed")
675 shutil.rmtree(cache_root)
676 _write_owner(cache_root, CACHE_OWNER)
677 outside = root /
"outside"
678 outside.write_text(
"keep\n", encoding=
"ascii")
679 Path(f
"{cache}.part").symlink_to(outside)
680 if _run_shell(cache_prepare_script(str(cache))).returncode == 0:
681 failures.append(
"planted runner-cache part symlink was accepted")
682 if outside.read_text(encoding=
"ascii") !=
"keep\n":
683 failures.append(
"planted runner-cache part symlink target was changed")
684 Path(f
"{cache}.part").unlink()
685 cache.symlink_to(outside)
686 if _run_shell(cache_prepare_script(str(cache))).returncode == 0:
687 failures.append(
"planted runner-cache destination symlink was accepted")
688 if outside.read_text(encoding=
"ascii") !=
"keep\n":
689 failures.append(
"planted runner-cache destination target was changed")
693def _link_selftest(root: Path) -> list[str]:
694 """Prove installed internal links pass while external links fail closed."""
695 failures: list[str] = []
696 authority = root /
"authority"
698 (authority /
"target").write_text(
"owned\n", encoding=
"ascii")
699 (authority /
"internal").symlink_to(
"target")
700 if not _links_stay_within(authority):
701 failures.append(
"internal staged-authority symlink was refused")
702 outside = root /
"outside-link-target"
703 outside.write_text(
"external\n", encoding=
"ascii")
704 (authority /
"escaping").symlink_to(outside)
705 if _links_stay_within(authority):
706 failures.append(
"escaping staged-authority symlink was accepted")
710def _probe_selftest(root: Path) -> list[str]:
711 """Prove missing/stale drift and unsafe metadata remain distinct."""
712 failures: list[str] = []
713 stage = root /
"probe-stage"
714 missing = _run_shell(
"\n".join([
"set -euo pipefail", *stage_probe_lines(
"0" * 64, str(stage))]))
715 if missing.returncode != REMOTE_APPLY_REQUIRED_STATUS:
716 failures.append(
"missing WSL stage was not classified apply-required")
717 _write_owner(stage, STAGE_OWNER)
718 for member
in STAGE_MEMBERS:
719 target = stage / member
720 if member
in STAGE_DIRECTORY_MEMBERS:
721 target.mkdir(parents=
True, exist_ok=
True)
723 target.parent.mkdir(parents=
True, exist_ok=
True)
724 target.write_text(f
"fixture:{member}\n", encoding=
"ascii")
726 generation = stage_generation(stage)
727 marker = stage / GENERATION_FILE
728 marker.write_text(f
"{generation}\n", encoding=
"ascii")
729 marker.chmod(ROOT_READ_MODE)
730 probe =
"\n".join([
"set -euo pipefail", *stage_probe_lines(generation, str(stage))])
731 if _run_shell(probe).returncode:
732 failures.append(
"matching authenticated WSL generation was refused")
734 marker.write_text(f
"{'1' * SHA256_HEX_LENGTH}\n", encoding=
"ascii")
735 marker.chmod(ROOT_READ_MODE)
736 if _run_shell(probe).returncode != REMOTE_APPLY_REQUIRED_STATUS:
737 failures.append(
"stale WSL generation was not classified apply-required")
739 marker.write_text(f
"{generation}\n", encoding=
"ascii")
741 if _run_shell(probe).returncode != 1:
742 failures.append(
"unsafe WSL generation metadata was classified as drift")
746def _transaction_lock_selftest(root: Path) -> list[str]:
747 """Prove readers coexist, exclude writers, and leave no check residue."""
748 failures: list[str] = []
749 lock_root = root /
"lock"
750 lock_root.mkdir(mode=0o755)
751 reader_lines = transaction_lock_lines(
752 exclusive=
False, lock_root=str(lock_root), owner_uid=os.getuid()
754 reader_script =
"\n".join([
"set -euo pipefail", *reader_lines,
"echo READY",
"read -r _"])
755 holder = subprocess.Popen(
756 [
"/bin/bash",
"-c", reader_script],
757 stdin=subprocess.PIPE,
758 stdout=subprocess.PIPE,
759 stderr=subprocess.PIPE,
762 if holder.stdout
is None or holder.stdin
is None:
764 holder.wait(timeout=5)
765 return [
"WSL reader lock selftest did not create its observation pipes"]
766 if holder.stdout.readline().strip() !=
"READY":
767 failures.append(
"WSL reader lock did not acquire")
768 writer_lines = transaction_lock_lines(
769 exclusive=
True, lock_root=str(lock_root), owner_uid=os.getuid()
771 writer_lines[-1] =
"/usr/bin/flock -xn 9"
772 if _run_shell(
"\n".join([
"set -euo pipefail", *writer_lines])).returncode == 0:
773 failures.append(
"WSL writer entered while a reader held the generation")
775 holder.wait(timeout=5)
776 if _run_shell(
"\n".join([
"set -euo pipefail", *writer_lines])).returncode:
777 failures.append(
"WSL writer did not enter after readers exited")
778 if any(lock_root.iterdir()):
779 failures.append(
"WSL check lock left durable residue")
780 if holder.returncode == 0:
781 failures.append(
"killed WSL check did not terminate its lock holder")
782 sticky_root = root /
"sticky-lock"
784 sticky_root.chmod(0o1777)
785 sticky_lines = transaction_lock_lines(
786 exclusive=
True, lock_root=str(sticky_root), owner_uid=os.getuid()
788 sticky_lines[-1] =
"/usr/bin/flock -xn 9"
789 if _run_shell(
"\n".join([
"set -euo pipefail", *sticky_lines])).returncode:
790 failures.append(
"root-owned sticky WSL lock authority was refused")
794def _cache_receiver_selftest() -> list[str]:
795 """Prove the receiver is exclusive and inert to the Windows command shell."""
797 "wsl -d Ubuntu -u root -e /usr/bin/env -i HOME=/root PATH=/usr/bin:/bin "
798 "/usr/bin/dd of=/opt/ra8-infra-cache/ra8-ci-runner.tar.part "
799 "bs=4M conv=fsync,excl status=none"
801 if cache_receive_command(
"Ubuntu") != expected:
802 return [
"WSL runner-image receiver argv drifted"]
804 cache_receive_command(
"Ubuntu&forged")
807 return [
"WSL runner-image receiver accepted Windows command syntax"]
810def run_selftest() -> list[str]:
811 """Exercise offline ownership and atomic-publication boundaries."""
812 with tempfile.TemporaryDirectory(prefix=
"ra8-wsl-stage-")
as raw:
815 _stage_selftest(root)
816 + _cache_selftest(root)
817 + _link_selftest(root)
818 + _probe_selftest(root)
819 + _transaction_lock_selftest(root)
820 + _cache_receiver_selftest()
822 if _bootstrap_action(
"apply", installed=
False) !=
"--ensure":
823 failures.append(
"mutable operator apply lost its authenticated ensure path")
824 if _bootstrap_action(
"apply", installed=
True) !=
"--verify-cache":
825 failures.append(
"installed WSL apply attempted to mutate root-owned uv inputs")
826 if _bootstrap_action(
"check", installed=
False) !=
"--verify-cache":
827 failures.append(
"WSL check attempted to mutate uv inputs")