3"""Structural checks for the HIL convergence front-door and transport edges."""
5from __future__
import annotations
8from dataclasses
import dataclass
13@dataclass(frozen=True)
15 """One playbook's authenticated dynamic-role contract."""
21 roles: tuple[str, ...]
24def _function(tree: ast.Module, name: str) -> ast.FunctionDef |
None:
25 """Return one unique top-level function."""
26 found = [node
for node
in tree.body
if isinstance(node, ast.FunctionDef)
and node.name == name]
27 return found[0]
if len(found) == 1
else None
30def _same(node: ast.AST, source: str) -> bool:
31 """Compare executable syntax while ignoring locations and comments."""
32 expected = ast.parse(source).body[0]
33 return ast.dump(node, include_attributes=
False) == ast.dump(expected, include_attributes=
False)
36def _index(function: ast.FunctionDef |
None, source: str) -> int:
37 """Find one unique exact top-level statement."""
40 found = [index
for index, node
in enumerate(function.body)
if _same(node, source)]
41 return found[0]
if len(found) == 1
else -1
44def _assigned(function: ast.FunctionDef |
None, name: str) -> ast.expr |
None:
45 """Return one unique top-level assignment value."""
50 for node
in function.body
51 if isinstance(node, ast.Assign)
52 and len(node.targets) == 1
53 and isinstance(node.targets[0], ast.Name)
54 and node.targets[0].id == name
56 return found[0]
if len(found) == 1
else None
60 function: ast.FunctionDef |
None,
65 """Return whether one module call has the exact first positional argv."""
70 for node
in ast.walk(function)
71 if isinstance(node, ast.Call)
72 and isinstance(node.func, ast.Attribute)
73 and isinstance(node.func.value, ast.Name)
74 and node.func.value.id == module
75 and node.func.attr == name
78 expected = ast.parse(expected_source, mode=
"eval").body
79 return len(found) == 1
and ast.dump(found[0], include_attributes=
False) == ast.dump(
80 expected, include_attributes=
False
84def _dispatch_order_errors(fleet: ast.Module) -> list[str]:
85 """Require selector refusal before the lock wrapper and inventory preview."""
86 errors: list[str] = []
87 converge = _function(fleet,
"cmd_converge")
89 "refusal = _converge_refusal(args, host, plays)",
90 "if refusal:\n return _fail(refusal)",
91 "guard = _bench_guard_argv(host, plays, args)",
93 "if guard:\n guardian = _bench_guard_subprocess_kwargs("
94 "args.command, fml.guardian_subprocess_kwargs)\n"
95 " return _run(guard, cwd=fm.REPO_ROOT, subprocess_kwargs=guardian)"
97 "rc = cmd_inventory(data, argparse.Namespace(stdout=False))",
99 indices = [_index(converge, statement)
for statement
in order]
100 if -1
in indices
or indices != sorted(indices):
101 errors.append(
"fleet.py: selector/extra-var refusal is not before lock and inventory")
102 refusal = _function(fleet,
"_converge_refusal")
104 'boundary = fb.control_flow_refusal(fb.FlowRequest(str(host["class"]), plays, '
105 'args.mode, args.tags, args.extra_var, bool(getattr(args, "trusted_tags", False))))'
107 if _index(refusal, boundary) < 0
or _index(refusal,
"if boundary:\n return boundary") < 0:
108 errors.append(
"fleet.py: bench control-flow refusal is not executable and exact")
112def _dispatch_errors(fleet: ast.Module, bench: ast.Module) -> list[str]:
113 """Require authentication before wrapper, inventory, or preview."""
114 errors = _dispatch_order_errors(fleet)
115 guard = _function(bench,
"guarded_argv")
118 " capability = _capability(request.environment)\n"
119 " if not authenticate(request.repo_root, capability):\n"
120 " raise BenchGuardError(INHERITED_LOCK_ERROR)\n"
123 if _index(guard,
"lock_id = _lock_id(request.environment)") < 0
or _index(guard, auth) < 0:
124 errors.append(
"fleet_bench.py: inherited lock is trusted without live authentication")
126 'return ["/bin/bash", "-p", '
127 'str(request.repo_root / "scripts/hil/bench.sh"), '
128 '"run", "--intent", "Ansible bench-affecting converge", '
129 '"--for", "2h", "--wait", "2h", "--", '
130 "str(request.fleet_script), *request.original_argv]"
132 if _index(guard, wrapper) < 0:
133 errors.append(
"fleet_bench.py: bench wrapper is not the exact privileged Bash transport")
134 live_auth = _function(bench,
"_live_lock_matches")
136 '["/bin/bash", "--noprofile", "--norc", "-p", "-c", script, '
137 '"ra8-lock", str(client), capability.lock_id, digest, broker_digest]'
139 if not _exact_call_argv(live_auth,
"subprocess",
"run", live_auth_argv):
141 "fleet_bench.py: live-lock verifier is not the exact privileged Bash transport"
143 bash_probe = _function(bench,
"_privileged_bash_selftest")
144 probe_argv =
'["/bin/bash", "--noprofile", "--norc", "-p", "-c", probe]'
145 if not _exact_call_argv(bash_probe,
"subprocess",
"run", probe_argv):
146 errors.append(
"fleet_bench.py: privileged Bash execution probe argv is not exact")
147 runtime = _function(bench,
"run_selftest")
148 if _index(runtime,
"failures = _privileged_bash_selftest()") < 0:
149 errors.append(
"fleet_bench.py: privileged Bash execution probe is not load-bearing")
150 controls = _function(bench,
"control_flow_refusal")
152 "if request.tags and not request.trusted_tags:\n"
153 ' return "bench-affecting applies do not accept --tags"',
154 "if request.extra_vars:\n"
155 ' return "bench-affecting applies do not accept raw --extra-var"',
157 if any(_index(controls, statement) < 0
for statement
in required):
158 errors.append(
"fleet_bench.py: arbitrary tags or extra vars remain accepted")
162def _native_environment_errors(runner: ast.Module, reach: ast.Module) -> list[str]:
163 """Require minimal child environment, absolute SSH, and link census."""
164 errors: list[str] = []
165 environment = _function(runner,
"ansible_environment")
166 expected_clean = ast.parse(
167 '{"HOME": pwd.getpwuid(os.getuid()).pw_dir, "LANG": "C.UTF-8", '
168 '"LC_ALL": "C.UTF-8", "PATH": "/usr/bin:/bin"}',
171 clean = _assigned(environment,
"clean")
172 if clean
is None or ast.dump(clean, include_attributes=
False) != ast.dump(
173 expected_clean, include_attributes=
False
175 errors.append(
"fleet runner: native Ansible child environment is not minimal")
176 link_call =
"link_errors = fpa.confined_link_errors(collections)"
177 if _index(environment, link_call) < 0:
178 errors.append(
"fleet runner: collection link census is not before callback use")
179 ssh_target = _function(reach,
"ssh_target")
180 expected_ssh = ast.parse(
'["/usr/bin/ssh", *SSH_OPTIONS]', mode=
"eval").body
181 ssh_argv = _assigned(ssh_target,
"argv")
182 if ssh_argv
is None or ast.dump(ssh_argv, include_attributes=
False) != ast.dump(
183 expected_ssh, include_attributes=
False
185 errors.append(
"fleet reach: SSH executable is not an absolute trusted authority")
189def _wsl_boundary_errors(model: ast.Module, stage: ast.Module) -> list[str]:
190 """Require env-empty WSL Bash and absolute local archive creation."""
191 errors: list[str] = []
192 remote = _function(model,
"remote_shell")
193 strings = set(_return_strings(remote))
196 " -u root -e /usr/bin/env -i HOME=/root PATH=/usr/bin:/bin /bin/bash -s",
199 if not required <= strings:
200 errors.append(
"fleet model: actual WSL boundary is not env-empty before Bash")
201 archive = _function(stage,
"_stage_archive")
202 tar_tool = _assigned(archive,
"tar_tool")
203 expected_tar = ast.parse(
'Path("/usr/bin/tar")', mode=
"eval").body
204 if tar_tool
is None or ast.dump(tar_tool, include_attributes=
False) != ast.dump(
205 expected_tar, include_attributes=
False
207 errors.append(
"fleet WSL stage: archive tool is not fixed /usr/bin/tar")
211def _return_strings(function: ast.FunctionDef |
None) -> list[str]:
212 """Return list-literal strings which are executed by rendered shell."""
217 for node
in ast.walk(function)
218 if isinstance(node, ast.Constant)
and isinstance(node.value, str)
222def _return_lines(function: ast.FunctionDef |
None) -> set[str]:
223 """Return exact nonempty shell lines from executable return literals."""
226 for value
in _return_strings(function)
227 for line
in value.splitlines()
232def _durability_errors(stage: ast.Module, wsl: ast.Module) -> list[str]:
233 """Require file/parent fsyncs on every stage/cache namespace publication."""
234 owner = _return_lines(_function(stage,
"_owned_shell"))
238 'sync_dir "$parent"',
240 if not required_owner <= set(owner):
241 return [
"fleet WSL stage: owned removal is not parent-fsynced"]
243 "stage_prepare_script": {
244 'sync_dir "$(dirname -- "$stage")"': 1,
245 'sync_dir "$incoming"': 1,
246 'sync_dir "$(dirname -- "$incoming")"': 1,
248 "stage_publish_script": {
'sync_dir "$(dirname -- "$stage")"': 3},
249 "cache_prepare_script": {
'sync_dir "$cache_root"': 2},
250 "cache_cleanup_script": {
'sync_dir "$cache_root"': 1},
251 "cache_publish_script": {
'sync_file "$part"': 1,
'sync_dir "$cache_root"': 1},
253 errors: list[str] = []
254 for name, wanted
in required.items():
257 for value
in _return_strings(_function(stage, name))
258 for line
in value.splitlines()
261 if any(lines.count(line) != count
for line, count
in wanted.items()):
262 errors.append(f
"fleet WSL stage: {name} lost crash-durable publication")
263 verify_lines = _return_lines(_function(wsl,
"_toolchain_verify_lines"))
265 'mv -f -- "$marker" "$managed_root/.ra8-infra-lock.sha256"',
266 'sync_file "$managed_root/.ra8-infra-lock.sha256"',
267 'sync_dir "$managed_root"',
269 if not marker_lines <= verify_lines:
270 errors.append(
"fleet WSL: managed lock marker is not crash durable")
274def _one_play(source: str, label: str) -> tuple[dict[str, object] |
None, list[str]]:
275 """Parse one exactly shaped playbook."""
277 document = yaml.safe_load(source)
278 except yaml.YAMLError:
279 return None, [f
"{label}: malformed YAML"]
280 if not isinstance(document, list)
or len(document) != 1
or not isinstance(document[0], dict):
281 return None, [f
"{label}: expected one play"]
282 return document[0], []
285def _playbook_frontdoor_errors(source: str, contract: FrontDoor) -> list[str]:
286 """Require dynamic role entry beneath one always-tagged guard."""
287 play, errors = _one_play(source, contract.label)
290 if play.get(
"roles"):
291 errors.append(f
"{contract.label}: static roles can bypass the authenticated front door")
292 pre = play.get(
"pre_tasks")
293 tasks = play.get(
"tasks")
294 if not isinstance(pre, list)
or len(pre) != 1
or not isinstance(tasks, list):
295 errors.append(f
"{contract.label}: guard/task front door is incomplete")
297 include = pre[0].get(
"ansible.builtin.include_role")
if isinstance(pre[0], dict)
else None
299 "name": contract.guard_role,
300 "tasks_from": contract.guard_file,
301 "apply": {
"tags": [
"always"]},
303 if include != expected_guard
or pre[0].get(
"tags") != [
"always"]:
304 errors.append(f
"{contract.label}: guard include is not exact and always-selected")
306 condition = f
"{contract.fact} | default(false) | bool"
308 role = task.get(
"ansible.builtin.include_role")
if isinstance(task, dict)
else None
310 not isinstance(role, dict)
311 or set(role) != {
"name"}
312 or task.get(
"when") != condition
313 or task.get(
"tags") != [
"always"]
316 f
"{contract.label}: a role is outside the authenticated dynamic front door"
319 seen.append(str(role[
"name"]))
320 if not errors
and tuple(seen) != contract.roles:
321 errors.append(f
"{contract.label}: guarded role closure drifted")
325def errors(inputs: dict[str, str]) -> list[str]:
326 """Return all v8 boundary findings, failing closed on syntax errors."""
329 key: ast.parse(inputs[key])
337 "fleet_runner_model",
342 return [
"HIL convergence v8: invalid governed Python"]
344 _dispatch_errors(trees[
"fleet"], trees[
"fleet_bench"])
345 + _native_environment_errors(trees[
"fleet_runner"], trees[
"fleet_reach"])
346 + _wsl_boundary_errors(trees[
"fleet_runner_model"], trees[
"fleet_wsl_stage"])
347 + _durability_errors(trees[
"fleet_wsl_stage"], trees[
"fleet_wsl"])
348 + _playbook_frontdoor_errors(
349 inputs[
"dev_playbook"],
353 "hil_mutation_guard.yml",
354 "dev_box_hil_mutation_authenticated",
358 + _playbook_frontdoor_errors(
359 inputs[
"bench_playbook"],
363 "transaction_guard.yml",
364 "hil_bench_transaction_authenticated",
365 (
"hil_bench",
"c6_toolchain",
"ad2_tools"),