ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
hil_convergence_safety_selftest_environment.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Environment and runner mutation cases for the HIL safety self-test."""
4
5from __future__ import annotations
6
7from collections.abc import Callable
8
9Scan = Callable[[dict[str, str]], list[str]]
10Mutate = Callable[[dict[str, str], str, str, str], dict[str, str]]
11RemoveManifestMember = Callable[[dict[str, str], str], dict[str, str]]
12RemoveLoopMember = Callable[[dict[str, str], str, str, str], dict[str, str]]
13
14
15class EnvironmentCaseError(ValueError):
16 """A structural environment self-test no longer has its expected cases."""
17
18
19def runner_runtime_directory_cases(
20 inputs: dict[str, str], scan: Scan, mutate: Mutate
21) -> list[tuple[str, bool]]:
22 """Return runtime-directory validation and allowlist mutations."""
23 mutations = (
24 (
25 "relative Ansible runtime directory acceptance",
26 "if not path.is_absolute():",
27 "if False:",
28 ),
29 (
30 "Ansible runtime directory owner-check removal",
31 "metadata.st_uid != os.getuid()",
32 "False",
33 ),
34 (
35 "Ansible runtime directory mode-check removal",
36 "stat.S_IMODE(metadata.st_mode) != PRIVATE_DIRECTORY_MODE",
37 "False",
38 ),
39 (
40 "private Ansible runtime mode widening",
41 "PRIVATE_DIRECTORY_MODE = 0o700",
42 "PRIVATE_DIRECTORY_MODE = 0o755",
43 ),
44 (
45 "Ansible runtime environment allowlist widening",
46 '("ANSIBLE_LOCAL_TEMP", "ANSIBLE_SSH_CONTROL_PATH_DIR")',
47 '("ANSIBLE_LOCAL_TEMP", "ANSIBLE_SSH_CONTROL_PATH_DIR", "TMPDIR")',
48 ),
49 (
50 "Ansible runtime directory validator bypass",
51 "value = _private_runtime_directory(environment, key)",
52 "value = environment.get(key)",
53 ),
54 )
55 return [
56 (label, bool(scan(mutate(inputs, "fleet_runner", old, new))))
57 for label, old, new in mutations
58 ]
59
60
61def _environment_variable_cases(
62 inputs: dict[str, str], scan: Scan, mutate: Mutate
63) -> list[tuple[str, bool]]:
64 """Return environment-variable sanitizer mutations."""
65 return [
66 (
67 "HIL caller-selected tool venv fires",
68 bool(
69 scan(
70 mutate(
71 inputs,
72 "hil_just",
73 'export RA8_TOOL_VENV := ""',
74 'export RA8_TOOL_VENV := env("RA8_TOOL_VENV", "")',
75 )
76 )
77 ),
78 ),
79 (
80 "Ansible setup sanitizer removal fires",
81 bool(
82 scan(
83 mutate(
84 inputs,
85 "setup_ansible",
86 "unset PYTHONHOME PYTHONPATH RA8_TOOL_VENV",
87 ": # sanitizer removed",
88 )
89 )
90 ),
91 ),
92 (
93 "toolchain provision TMPDIR sanitizer removal fires",
94 bool(
95 scan(
96 mutate(
97 inputs,
98 "provision_toolchain",
99 "unset PYTHONHOME PYTHONPATH RA8_TOOL_VENV TMPDIR",
100 "unset PYTHONHOME PYTHONPATH RA8_TOOL_VENV",
101 )
102 )
103 ),
104 ),
105 ]
106
107
108def _environment_path_cases(
109 inputs: dict[str, str], scan: Scan, mutate: Mutate
110) -> list[tuple[str, bool]]:
111 """Return fixed-path interpreter and shell mutations."""
112 return [
113 (
114 "HIL caller PATH inheritance fires",
115 bool(
116 scan(
117 mutate(
118 inputs,
119 "hil_just",
120 "export PATH := `/bin/bash -p "
121 "scripts/ci/lib/host_tool_path.sh --print-path`",
122 'export PATH := env("PATH", "")',
123 )
124 )
125 ),
126 ),
127 (
128 "toolchain provision PATH poisoning fires",
129 bool(
130 scan(
131 mutate(
132 inputs,
133 "provision_toolchain",
134 "PATH=/usr/local/bin:/usr/bin:/bin",
135 "PATH=${PATH}",
136 )
137 )
138 ),
139 ),
140 (
141 "infra bootstrap PATH Bash fires",
142 bool(
143 scan(
144 mutate(
145 inputs,
146 "infra_bootstrap",
147 '/bin/bash -p "${ROOT}/scripts/dev/setup_ansible.sh"',
148 'bash "${ROOT}/scripts/dev/setup_ansible.sh"',
149 )
150 )
151 ),
152 ),
153 ]
154
155
156def _environment_sanitizer_cases(
157 inputs: dict[str, str], scan: Scan, mutate: Mutate
158) -> list[tuple[str, bool]]:
159 """Return every public environment-sanitizer mutation."""
160 return _environment_variable_cases(inputs, scan, mutate) + _environment_path_cases(
161 inputs, scan, mutate
162 )
163
164
165def _authenticated_uv_runner_cases(
166 inputs: dict[str, str], scan: Scan, mutate: Mutate
167) -> list[tuple[str, bool]]:
168 """Return authenticated uv-runner mutations."""
169 return [
170 (
171 "infra authenticated uv runner removal fires",
172 bool(
173 scan(
174 mutate(
175 inputs,
176 "infra_sh",
177 "--run --no-config sync",
178 "--no-config sync",
179 )
180 )
181 ),
182 ),
183 (
184 "WSL authenticated uv runner removal fires",
185 bool(
186 scan(
187 mutate(
188 inputs,
189 "fleet_wsl",
190 '--run "$@"',
191 '--verify-cache "$@"',
192 )
193 )
194 ),
195 ),
196 ]
197
198
199def _container_helper_cases(
200 inputs: dict[str, str], scan: Scan, mutate: Mutate
201) -> list[tuple[str, bool]]:
202 """Return devcontainer uv-helper mutations."""
203 return [
204 (
205 "devcontainer uv helper allowlist removal fires",
206 bool(
207 scan(
208 mutate(
209 inputs,
210 "dockerignore",
211 "!scripts/dev/bootstrap_uv_exec.py\n",
212 "",
213 )
214 )
215 ),
216 ),
217 (
218 "devcontainer uv helper COPY removal fires",
219 bool(
220 scan(
221 mutate(
222 inputs,
223 "dockerfile",
224 " scripts/dev/bootstrap_uv_exec.py \\\n",
225 "",
226 )
227 )
228 ),
229 ),
230 (
231 "devcontainer uv helper canonical-input removal fires",
232 bool(
233 scan(
234 mutate(
235 inputs,
236 "devcontainer_image",
237 "644 scripts/dev/bootstrap_uv_exec.py\n",
238 "",
239 )
240 )
241 ),
242 ),
243 ]
244
245
246def _runner_helper_cases(
247 inputs: dict[str, str],
248 scan: Scan,
249 remove_manifest_member: RemoveManifestMember,
250 remove_loop_member: RemoveLoopMember,
251) -> list[tuple[str, bool]]:
252 """Return HIL and CI runner uv-helper mutations."""
253 return [
254 (
255 "HIL uv helper staging removal fires",
256 bool(scan(remove_manifest_member(inputs, "bootstrap_uv_exec.py"))),
257 ),
258 (
259 "CI runner uv helper readback removal fires",
260 bool(
261 scan(
262 remove_loop_member(
263 inputs,
264 "ci_runner",
265 "Read back every staged root-context authority byte-for-byte",
266 "scripts/dev/bootstrap_uv_exec.py",
267 )
268 )
269 ),
270 ),
271 (
272 "CI runner uv helper presence-proof removal fires",
273 bool(
274 scan(
275 remove_loop_member(
276 inputs,
277 "ci_runner",
278 "Assert both Dockerfiles and every locked Python input arrived",
279 "scripts/dev/bootstrap_uv_exec.py",
280 )
281 )
282 ),
283 ),
284 ]
285
286
287def _wsl_helper_cases(inputs: dict[str, str], scan: Scan, mutate: Mutate) -> list[tuple[str, bool]]:
288 """Return WSL uv-helper archive and path-proof mutations."""
289 return [
290 (
291 "WSL uv helper archive removal fires",
292 bool(
293 scan(
294 mutate(
295 inputs,
296 "fleet_wsl_stage",
297 ' "scripts/dev/bootstrap_uv_exec.py",\n',
298 "",
299 )
300 )
301 ),
302 ),
303 (
304 "WSL uv helper path-proof removal fires",
305 bool(
306 scan(
307 mutate(
308 inputs,
309 "fleet_wsl",
310 ' f"{stage}/scripts/dev/bootstrap_uv_exec.py",\n',
311 "",
312 )
313 )
314 ),
315 ),
316 ]
317
318
319def cases(
320 inputs: dict[str, str],
321 scan: Scan,
322 mutate: Mutate,
323 remove_manifest_member: RemoveManifestMember,
324 remove_loop_member: RemoveLoopMember,
325) -> list[tuple[str, bool]]:
326 """Return public environment and installer-boundary mutations."""
327 sanitizer_cases = _environment_sanitizer_cases(inputs, scan, mutate)
328 uv_runner_cases = _authenticated_uv_runner_cases(inputs, scan, mutate)
329 container_cases = _container_helper_cases(inputs, scan, mutate)
330 runner_cases = _runner_helper_cases(inputs, scan, remove_manifest_member, remove_loop_member)
331 wsl_cases = _wsl_helper_cases(inputs, scan, mutate)
332 if not all((sanitizer_cases, uv_runner_cases, container_cases, runner_cases, wsl_cases)):
333 message = "environment case helper returned no mutation cases"
334 raise EnvironmentCaseError(message)
335 return sanitizer_cases + uv_runner_cases + container_cases + runner_cases + wsl_cases