ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
shell_entrypoint_policy.py
Go to the documentation of this file.
1# SPDX-License-Identifier: MIT
2# Copyright (c) 2026 Brighton Sikarskie
3"""Typed authority for every first-party shell entry point.
4
5This table is intentionally exhaustive. The shebang gate compares it with the
6repository's canonical shell census, so a new shell file cannot inherit any
7policy by naming convention. Startup security, entry/source usage, dialect,
8and executable mode are independent axes. Security-pinned entries use the
9canonical combined preamble: shebang, SPDX, copyright, then the exact
10``SHEBANG-SECURITY`` rationale. A privileged sourced-only helper,
11for example, must keep its protected header but can only be sourced by a
12privileged parent; it never becomes a launchable privileged entry merely
13because it uses the protected header.
14"""
15
16from __future__ import annotations
17
18from dataclasses import dataclass
19from enum import StrEnum
20
21from shell_entrypoint_policy_ci import CI_POLICY_ROWS
22from shell_entrypoint_policy_hil import HIL_POLICY_ROWS, ShellPolicyRow
23
24
25class ShellSecurity(StrEnum):
26 """Startup trust required by a shell file."""
27
28 PORTABLE = "portable"
29 PRIVILEGED = "privileged"
30
31
32class ShellUsage(StrEnum):
33 """Whether a file is an entry point, a sourced helper, or both."""
34
35 ENTRY = "entry"
36 SOURCED_ONLY = "sourced-only"
37 DUAL_USE = "dual-use"
38
39
40class ShellDialect(StrEnum):
41 """Exact interpreter dialect for portable headers."""
42
43 BASH = "bash"
44 POSIX_SH = "posix-sh"
45
46
47class DuplicateShellPolicyError(ValueError):
48 """A path appeared in more than one typed policy domain."""
49
50
51@dataclass(frozen=True)
52class ShellPolicy:
53 """One shell path's independent startup, usage, dialect, and mode contract."""
54
55 security: ShellSecurity
56 usage: ShellUsage
57 dialect: ShellDialect
58 executable: bool
59 source_requires_privileged_parent: bool
60
61
62PRIVILEGED_SHEBANG = "#!/bin/bash -p"
63PRIVILEGED_REASON = (
64 "# SHEBANG-SECURITY: -p blocks BASH_ENV and exported-function startup injection."
65)
66PORTABLE_SHEBANG = "#!/usr/bin/env bash"
67PORTABLE_SH_SHEBANG = "#!/usr/bin/env sh"
68
69_BASE_SHELL_POLICIES: dict[str, ShellPolicy] = {
70 "apps/host/mdl/tests/http_integration.sh": ShellPolicy(
71 ShellSecurity.PORTABLE,
72 ShellUsage.ENTRY,
73 ShellDialect.BASH,
74 executable=True,
75 source_requires_privileged_parent=False,
76 ),
77 "apps/host/mdl/tests/integration.sh": ShellPolicy(
78 ShellSecurity.PORTABLE,
79 ShellUsage.ENTRY,
80 ShellDialect.BASH,
81 executable=True,
82 source_requires_privileged_parent=False,
83 ),
84 "coprocessor/esp32c6/build.sh": ShellPolicy(
85 ShellSecurity.PRIVILEGED,
86 ShellUsage.ENTRY,
87 ShellDialect.BASH,
88 executable=True,
89 source_requires_privileged_parent=False,
90 ),
91 "coprocessor/esp32c6/flash.sh": ShellPolicy(
92 ShellSecurity.PRIVILEGED,
93 ShellUsage.ENTRY,
94 ShellDialect.BASH,
95 executable=True,
96 source_requires_privileged_parent=False,
97 ),
98 "examples/ek_ra8d2/hw_pending/ereader_m33/tests/scripts/emu_handoff_gate.sh": ShellPolicy(
99 ShellSecurity.PORTABLE,
100 ShellUsage.ENTRY,
101 ShellDialect.BASH,
102 executable=True,
103 source_requires_privileged_parent=False,
104 ),
105 "examples/ek_ra8d2/hw_pending/ereader_m33/tests/scripts/emu_render_gate.sh": ShellPolicy(
106 ShellSecurity.PORTABLE,
107 ShellUsage.ENTRY,
108 ShellDialect.BASH,
109 executable=True,
110 source_requires_privileged_parent=False,
111 ),
112 "examples/ek_ra8d2/hw_validated/hil/dfu_copy_to_run/scripts/build_payload.sh": ShellPolicy(
113 ShellSecurity.PORTABLE,
114 ShellUsage.ENTRY,
115 ShellDialect.BASH,
116 executable=True,
117 source_requires_privileged_parent=False,
118 ),
119 (
120 "examples/ek_ra8d2/hw_validated/hil/glcdc_render/tests/scripts/ra8_emulator_fb_crc.sh"
121 ): ShellPolicy(
122 ShellSecurity.PORTABLE,
123 ShellUsage.ENTRY,
124 ShellDialect.BASH,
125 executable=True,
126 source_requires_privileged_parent=False,
127 ),
128 "infra/bootstrap.sh": ShellPolicy(
129 ShellSecurity.PRIVILEGED,
130 ShellUsage.ENTRY,
131 ShellDialect.BASH,
132 executable=True,
133 source_requires_privileged_parent=False,
134 ),
135 "infra/network/ap_openwrt.sh": ShellPolicy(
136 ShellSecurity.PRIVILEGED,
137 ShellUsage.ENTRY,
138 ShellDialect.BASH,
139 executable=True,
140 source_requires_privileged_parent=False,
141 ),
142 "infra/network/verify_bench_wifi.sh": ShellPolicy(
143 ShellSecurity.PRIVILEGED,
144 ShellUsage.ENTRY,
145 ShellDialect.BASH,
146 executable=True,
147 source_requires_privileged_parent=False,
148 ),
149 "scripts/builders/all_examples.sh": ShellPolicy(
150 ShellSecurity.PORTABLE,
151 ShellUsage.ENTRY,
152 ShellDialect.BASH,
153 executable=True,
154 source_requires_privileged_parent=False,
155 ),
156 "scripts/builders/books.sh": ShellPolicy(
157 ShellSecurity.PORTABLE,
158 ShellUsage.ENTRY,
159 ShellDialect.BASH,
160 executable=True,
161 source_requires_privileged_parent=False,
162 ),
163 "scripts/builders/build_host_tools.sh": ShellPolicy(
164 ShellSecurity.PORTABLE,
165 ShellUsage.ENTRY,
166 ShellDialect.BASH,
167 executable=True,
168 source_requires_privileged_parent=False,
169 ),
170 "scripts/builders/build_shared_libs.sh": ShellPolicy(
171 ShellSecurity.PORTABLE,
172 ShellUsage.ENTRY,
173 ShellDialect.BASH,
174 executable=True,
175 source_requires_privileged_parent=False,
176 ),
177 "scripts/builders/docs.sh": ShellPolicy(
178 ShellSecurity.PORTABLE,
179 ShellUsage.ENTRY,
180 ShellDialect.BASH,
181 executable=True,
182 source_requires_privileged_parent=False,
183 ),
184 "scripts/builders/host_cmake.sh": ShellPolicy(
185 ShellSecurity.PORTABLE,
186 ShellUsage.ENTRY,
187 ShellDialect.BASH,
188 executable=True,
189 source_requires_privileged_parent=False,
190 ),
191 "scripts/builders/init_fuzz_corpora.sh": ShellPolicy(
192 ShellSecurity.PORTABLE,
193 ShellUsage.ENTRY,
194 ShellDialect.BASH,
195 executable=True,
196 source_requires_privileged_parent=False,
197 ),
198 "scripts/builders/lib/app_batch.sh": ShellPolicy(
199 ShellSecurity.PORTABLE,
200 ShellUsage.SOURCED_ONLY,
201 ShellDialect.BASH,
202 executable=False,
203 source_requires_privileged_parent=False,
204 ),
205 "scripts/builders/provision_doxygen.sh": ShellPolicy(
206 ShellSecurity.PRIVILEGED,
207 ShellUsage.ENTRY,
208 ShellDialect.BASH,
209 executable=False,
210 source_requires_privileged_parent=False,
211 ),
212 "scripts/builders/publish_docs.sh": ShellPolicy(
213 ShellSecurity.PRIVILEGED,
214 ShellUsage.ENTRY,
215 ShellDialect.BASH,
216 executable=True,
217 source_requires_privileged_parent=False,
218 ),
219 "scripts/builders/select_host_compiler.sh": ShellPolicy(
220 ShellSecurity.PORTABLE,
221 ShellUsage.SOURCED_ONLY,
222 ShellDialect.BASH,
223 executable=False,
224 source_requires_privileged_parent=False,
225 ),
226 "scripts/checks/check_nsc_cmse.sh": ShellPolicy(
227 ShellSecurity.PORTABLE,
228 ShellUsage.ENTRY,
229 ShellDialect.BASH,
230 executable=True,
231 source_requires_privileged_parent=False,
232 ),
233 "scripts/checks/check_stack_usage.sh": ShellPolicy(
234 ShellSecurity.PORTABLE,
235 ShellUsage.ENTRY,
236 ShellDialect.BASH,
237 executable=True,
238 source_requires_privileged_parent=False,
239 ),
240 "scripts/checks/check_unicorn_version.sh": ShellPolicy(
241 ShellSecurity.PORTABLE,
242 ShellUsage.ENTRY,
243 ShellDialect.BASH,
244 executable=True,
245 source_requires_privileged_parent=False,
246 ),
247 "scripts/checks/clang_tidy.sh": ShellPolicy(
248 ShellSecurity.PORTABLE,
249 ShellUsage.ENTRY,
250 ShellDialect.BASH,
251 executable=True,
252 source_requires_privileged_parent=False,
253 ),
254 "scripts/checks/cppcheck.sh": ShellPolicy(
255 ShellSecurity.PRIVILEGED,
256 ShellUsage.ENTRY,
257 ShellDialect.BASH,
258 executable=True,
259 source_requires_privileged_parent=False,
260 ),
261 "scripts/checks/format_code.sh": ShellPolicy(
262 ShellSecurity.PORTABLE,
263 ShellUsage.ENTRY,
264 ShellDialect.BASH,
265 executable=True,
266 source_requires_privileged_parent=False,
267 ),
268 "scripts/checks/format_tree.sh": ShellPolicy(
269 ShellSecurity.PORTABLE,
270 ShellUsage.ENTRY,
271 ShellDialect.BASH,
272 executable=True,
273 source_requires_privileged_parent=False,
274 ),
275 "scripts/checks/lint_selftest.sh": ShellPolicy(
276 ShellSecurity.PRIVILEGED,
277 ShellUsage.ENTRY,
278 ShellDialect.BASH,
279 executable=True,
280 source_requires_privileged_parent=False,
281 ),
282 "scripts/checks/misra_check.sh": ShellPolicy(
283 ShellSecurity.PORTABLE,
284 ShellUsage.ENTRY,
285 ShellDialect.BASH,
286 executable=True,
287 source_requires_privileged_parent=False,
288 ),
289 "scripts/checks/misra_check_inner.sh": ShellPolicy(
290 ShellSecurity.PORTABLE,
291 ShellUsage.ENTRY,
292 ShellDialect.BASH,
293 executable=True,
294 source_requires_privileged_parent=False,
295 ),
296 "scripts/checks/misra/selftest.sh": ShellPolicy(
297 ShellSecurity.PORTABLE,
298 ShellUsage.SOURCED_ONLY,
299 ShellDialect.BASH,
300 executable=False,
301 source_requires_privileged_parent=False,
302 ),
303 "scripts/checks/osv_scan.sh": ShellPolicy(
304 ShellSecurity.PORTABLE,
305 ShellUsage.ENTRY,
306 ShellDialect.BASH,
307 executable=True,
308 source_requires_privileged_parent=False,
309 ),
310 "scripts/checks/run_fuzz.sh": ShellPolicy(
311 ShellSecurity.PORTABLE,
312 ShellUsage.ENTRY,
313 ShellDialect.BASH,
314 executable=True,
315 source_requires_privileged_parent=False,
316 ),
317 "scripts/checks/scan_build.sh": ShellPolicy(
318 ShellSecurity.PORTABLE,
319 ShellUsage.ENTRY,
320 ShellDialect.BASH,
321 executable=True,
322 source_requires_privileged_parent=False,
323 ),
324 "scripts/checks/tidy/collect.sh": ShellPolicy(
325 ShellSecurity.PORTABLE,
326 ShellUsage.SOURCED_ONLY,
327 ShellDialect.BASH,
328 executable=False,
329 source_requires_privileged_parent=False,
330 ),
331 "scripts/checks/tidy/compile_db.sh": ShellPolicy(
332 ShellSecurity.PORTABLE,
333 ShellUsage.SOURCED_ONLY,
334 ShellDialect.BASH,
335 executable=False,
336 source_requires_privileged_parent=False,
337 ),
338 "scripts/checks/tidy/invoke.sh": ShellPolicy(
339 ShellSecurity.PORTABLE,
340 ShellUsage.SOURCED_ONLY,
341 ShellDialect.BASH,
342 executable=False,
343 source_requires_privileged_parent=False,
344 ),
345 "scripts/checks/tidy/pass_args.sh": ShellPolicy(
346 ShellSecurity.PORTABLE,
347 ShellUsage.SOURCED_ONLY,
348 ShellDialect.BASH,
349 executable=False,
350 source_requires_privileged_parent=False,
351 ),
352 "scripts/checks/tidy/passes.sh": ShellPolicy(
353 ShellSecurity.PORTABLE,
354 ShellUsage.SOURCED_ONLY,
355 ShellDialect.BASH,
356 executable=False,
357 source_requires_privileged_parent=False,
358 ),
359 "scripts/checks/tidy/selftest.sh": ShellPolicy(
360 ShellSecurity.PORTABLE,
361 ShellUsage.SOURCED_ONLY,
362 ShellDialect.BASH,
363 executable=False,
364 source_requires_privileged_parent=False,
365 ),
366 "scripts/dev/agent_workspace.sh": ShellPolicy(
367 ShellSecurity.PRIVILEGED,
368 ShellUsage.ENTRY,
369 ShellDialect.BASH,
370 executable=True,
371 source_requires_privileged_parent=False,
372 ),
373 "scripts/dev/agent_workspace_selftest.sh": ShellPolicy(
374 ShellSecurity.PORTABLE,
375 ShellUsage.ENTRY,
376 ShellDialect.BASH,
377 executable=True,
378 source_requires_privileged_parent=False,
379 ),
380 "scripts/dev/debug.sh": ShellPolicy(
381 ShellSecurity.PRIVILEGED,
382 ShellUsage.ENTRY,
383 ShellDialect.BASH,
384 executable=True,
385 source_requires_privileged_parent=False,
386 ),
387 "scripts/dev/exfat_macos_interop.sh": ShellPolicy(
388 ShellSecurity.PORTABLE,
389 ShellUsage.ENTRY,
390 ShellDialect.BASH,
391 executable=True,
392 source_requires_privileged_parent=False,
393 ),
394 "scripts/dev/flash.sh": ShellPolicy(
395 ShellSecurity.PRIVILEGED,
396 ShellUsage.ENTRY,
397 ShellDialect.BASH,
398 executable=True,
399 source_requires_privileged_parent=False,
400 ),
401 "scripts/dev/git_environment.sh": ShellPolicy(
402 ShellSecurity.PRIVILEGED,
403 ShellUsage.SOURCED_ONLY,
404 ShellDialect.BASH,
405 executable=False,
406 source_requires_privileged_parent=True,
407 ),
408 "scripts/dev/hil_cache_repair.sh": ShellPolicy(
409 ShellSecurity.PRIVILEGED,
410 ShellUsage.ENTRY,
411 ShellDialect.BASH,
412 executable=True,
413 source_requires_privileged_parent=False,
414 ),
415 "scripts/dev/infra.sh": ShellPolicy(
416 ShellSecurity.PORTABLE,
417 ShellUsage.ENTRY,
418 ShellDialect.BASH,
419 executable=True,
420 source_requires_privileged_parent=False,
421 ),
422 "scripts/dev/monitor.sh": ShellPolicy(
423 ShellSecurity.PRIVILEGED,
424 ShellUsage.ENTRY,
425 ShellDialect.BASH,
426 executable=True,
427 source_requires_privileged_parent=False,
428 ),
429 "scripts/dev/openocd_debug.sh": ShellPolicy(
430 ShellSecurity.PRIVILEGED,
431 ShellUsage.ENTRY,
432 ShellDialect.BASH,
433 executable=True,
434 source_requires_privileged_parent=False,
435 ),
436 "scripts/dev/openocd_flash.sh": ShellPolicy(
437 ShellSecurity.PRIVILEGED,
438 ShellUsage.ENTRY,
439 ShellDialect.BASH,
440 executable=True,
441 source_requires_privileged_parent=False,
442 ),
443 "scripts/dev/ozone.sh": ShellPolicy(
444 ShellSecurity.PRIVILEGED,
445 ShellUsage.ENTRY,
446 ShellDialect.BASH,
447 executable=True,
448 source_requires_privileged_parent=False,
449 ),
450 "scripts/dev/provision_dev_box_toolchain.sh": ShellPolicy(
451 ShellSecurity.PRIVILEGED,
452 ShellUsage.ENTRY,
453 ShellDialect.BASH,
454 executable=True,
455 source_requires_privileged_parent=False,
456 ),
457 "scripts/dev/provision_dev_box_toolchain_selftest.bash": ShellPolicy(
458 ShellSecurity.PRIVILEGED,
459 ShellUsage.SOURCED_ONLY,
460 ShellDialect.BASH,
461 executable=False,
462 source_requires_privileged_parent=True,
463 ),
464 "scripts/dev/remote_gdb_server.sh": ShellPolicy(
465 ShellSecurity.PRIVILEGED,
466 ShellUsage.ENTRY,
467 ShellDialect.BASH,
468 executable=True,
469 source_requires_privileged_parent=False,
470 ),
471 "scripts/dev/run_just.sh": ShellPolicy(
472 ShellSecurity.PRIVILEGED,
473 ShellUsage.ENTRY,
474 ShellDialect.BASH,
475 executable=True,
476 source_requires_privileged_parent=False,
477 ),
478 "scripts/dev/setup_ansible.sh": ShellPolicy(
479 ShellSecurity.PRIVILEGED,
480 ShellUsage.ENTRY,
481 ShellDialect.BASH,
482 executable=True,
483 source_requires_privileged_parent=False,
484 ),
485 "scripts/dev/setup_python.sh": ShellPolicy(
486 ShellSecurity.PRIVILEGED,
487 ShellUsage.ENTRY,
488 ShellDialect.BASH,
489 executable=True,
490 source_requires_privileged_parent=False,
491 ),
492 "scripts/emu/eil_all.sh": ShellPolicy(
493 ShellSecurity.PRIVILEGED,
494 ShellUsage.ENTRY,
495 ShellDialect.BASH,
496 executable=False,
497 source_requires_privileged_parent=False,
498 ),
499 "scripts/emu/emu_fixtures.sh": ShellPolicy(
500 ShellSecurity.PORTABLE,
501 ShellUsage.SOURCED_ONLY,
502 ShellDialect.BASH,
503 executable=False,
504 source_requires_privileged_parent=False,
505 ),
506 "scripts/emu/matrix.sh": ShellPolicy(
507 ShellSecurity.PORTABLE,
508 ShellUsage.ENTRY,
509 ShellDialect.BASH,
510 executable=True,
511 source_requires_privileged_parent=False,
512 ),
513 "scripts/emu/matrix_triage.sh": ShellPolicy(
514 ShellSecurity.PORTABLE,
515 ShellUsage.ENTRY,
516 ShellDialect.BASH,
517 executable=True,
518 source_requires_privileged_parent=False,
519 ),
520 "scripts/emu/setup_macos.sh": ShellPolicy(
521 ShellSecurity.PRIVILEGED,
522 ShellUsage.ENTRY,
523 ShellDialect.BASH,
524 executable=True,
525 source_requires_privileged_parent=False,
526 ),
527 "scripts/emu/smoke.sh": ShellPolicy(
528 ShellSecurity.PORTABLE,
529 ShellUsage.ENTRY,
530 ShellDialect.BASH,
531 executable=True,
532 source_requires_privileged_parent=False,
533 ),
534 "scripts/emu/smoke_apps.sh": ShellPolicy(
535 ShellSecurity.PORTABLE,
536 ShellUsage.SOURCED_ONLY,
537 ShellDialect.BASH,
538 executable=False,
539 source_requires_privileged_parent=False,
540 ),
541 "scripts/emu/smoke_assert.sh": ShellPolicy(
542 ShellSecurity.PORTABLE,
543 ShellUsage.SOURCED_ONLY,
544 ShellDialect.BASH,
545 executable=False,
546 source_requires_privileged_parent=False,
547 ),
548 "scripts/emu/smoke_run.sh": ShellPolicy(
549 ShellSecurity.PORTABLE,
550 ShellUsage.SOURCED_ONLY,
551 ShellDialect.BASH,
552 executable=False,
553 source_requires_privileged_parent=False,
554 ),
555 "scripts/gen/build_chapter_map.sh": ShellPolicy(
556 ShellSecurity.PORTABLE,
557 ShellUsage.ENTRY,
558 ShellDialect.BASH,
559 executable=True,
560 source_requires_privileged_parent=False,
561 ),
562 "scripts/gen/gen_ra8_media_proto.sh": ShellPolicy(
563 ShellSecurity.PORTABLE,
564 ShellUsage.ENTRY,
565 ShellDialect.BASH,
566 executable=True,
567 source_requires_privileged_parent=False,
568 ),
569 "scripts/git/commit-msg": ShellPolicy(
570 ShellSecurity.PRIVILEGED,
571 ShellUsage.ENTRY,
572 ShellDialect.BASH,
573 executable=True,
574 source_requires_privileged_parent=False,
575 ),
576 "scripts/git/github_askpass.sh": ShellPolicy(
577 ShellSecurity.PORTABLE,
578 ShellUsage.ENTRY,
579 ShellDialect.BASH,
580 executable=True,
581 source_requires_privileged_parent=False,
582 ),
583 "scripts/git/hook-launcher": ShellPolicy(
584 ShellSecurity.PRIVILEGED,
585 ShellUsage.ENTRY,
586 ShellDialect.BASH,
587 executable=True,
588 source_requires_privileged_parent=False,
589 ),
590 "scripts/git/install-hooks.sh": ShellPolicy(
591 ShellSecurity.PRIVILEGED,
592 ShellUsage.ENTRY,
593 ShellDialect.BASH,
594 executable=True,
595 source_requires_privileged_parent=False,
596 ),
597 "scripts/git/post-checkout": ShellPolicy(
598 ShellSecurity.PORTABLE,
599 ShellUsage.ENTRY,
600 ShellDialect.POSIX_SH,
601 executable=True,
602 source_requires_privileged_parent=False,
603 ),
604 "scripts/git/post-commit": ShellPolicy(
605 ShellSecurity.PORTABLE,
606 ShellUsage.ENTRY,
607 ShellDialect.POSIX_SH,
608 executable=True,
609 source_requires_privileged_parent=False,
610 ),
611 "scripts/git/post-merge": ShellPolicy(
612 ShellSecurity.PORTABLE,
613 ShellUsage.ENTRY,
614 ShellDialect.POSIX_SH,
615 executable=True,
616 source_requires_privileged_parent=False,
617 ),
618 "scripts/git/pre-commit": ShellPolicy(
619 ShellSecurity.PRIVILEGED,
620 ShellUsage.ENTRY,
621 ShellDialect.BASH,
622 executable=True,
623 source_requires_privileged_parent=False,
624 ),
625 "scripts/git/pre-push": ShellPolicy(
626 ShellSecurity.PRIVILEGED,
627 ShellUsage.ENTRY,
628 ShellDialect.BASH,
629 executable=True,
630 source_requires_privileged_parent=False,
631 ),
632 "scripts/report/mcdc_report.sh": ShellPolicy(
633 ShellSecurity.PORTABLE,
634 ShellUsage.ENTRY,
635 ShellDialect.BASH,
636 executable=True,
637 source_requires_privileged_parent=False,
638 ),
639 "scripts/report/tree_coverage.sh": ShellPolicy(
640 ShellSecurity.PORTABLE,
641 ShellUsage.ENTRY,
642 ShellDialect.BASH,
643 executable=True,
644 source_requires_privileged_parent=False,
645 ),
646 "scripts/secrets/openbao_configure.sh": ShellPolicy(
647 ShellSecurity.PRIVILEGED,
648 ShellUsage.ENTRY,
649 ShellDialect.BASH,
650 executable=True,
651 source_requires_privileged_parent=False,
652 ),
653 "scripts/secrets/openbao_unseal.sh": ShellPolicy(
654 ShellSecurity.PRIVILEGED,
655 ShellUsage.ENTRY,
656 ShellDialect.BASH,
657 executable=True,
658 source_requires_privileged_parent=False,
659 ),
660 "scripts/secrets/rot_provision.sh": ShellPolicy(
661 ShellSecurity.PRIVILEGED,
662 ShellUsage.ENTRY,
663 ShellDialect.BASH,
664 executable=True,
665 source_requires_privileged_parent=False,
666 ),
667 "tests/build_tests.sh": ShellPolicy(
668 ShellSecurity.PORTABLE,
669 ShellUsage.ENTRY,
670 ShellDialect.BASH,
671 executable=True,
672 source_requires_privileged_parent=False,
673 ),
674 "tests/fixtures/epub/run_probe.sh": ShellPolicy(
675 ShellSecurity.PORTABLE,
676 ShellUsage.ENTRY,
677 ShellDialect.BASH,
678 executable=True,
679 source_requires_privileged_parent=False,
680 ),
681 "tests/run_tests.sh": ShellPolicy(
682 ShellSecurity.PORTABLE,
683 ShellUsage.ENTRY,
684 ShellDialect.BASH,
685 executable=True,
686 source_requires_privileged_parent=False,
687 ),
688 "tools/exfat_mkimage/tests/integration.sh": ShellPolicy(
689 ShellSecurity.PORTABLE,
690 ShellUsage.ENTRY,
691 ShellDialect.BASH,
692 executable=True,
693 source_requires_privileged_parent=False,
694 ),
695 "tools/glyph_bench/tests/integration.sh": ShellPolicy(
696 ShellSecurity.PORTABLE,
697 ShellUsage.SOURCED_ONLY,
698 ShellDialect.BASH,
699 executable=False,
700 source_requires_privileged_parent=False,
701 ),
702 "tools/mkbookimg/tests/integration.sh": ShellPolicy(
703 ShellSecurity.PORTABLE,
704 ShellUsage.ENTRY,
705 ShellDialect.BASH,
706 executable=True,
707 source_requires_privileged_parent=False,
708 ),
709 "tools/mkfontimg/tests/integration.sh": ShellPolicy(
710 ShellSecurity.PORTABLE,
711 ShellUsage.ENTRY,
712 ShellDialect.BASH,
713 executable=True,
714 source_requires_privileged_parent=False,
715 ),
716 "tools/rabook_imagepack/tests/check_production_surface.sh": ShellPolicy(
717 ShellSecurity.PORTABLE,
718 ShellUsage.ENTRY,
719 ShellDialect.POSIX_SH,
720 executable=False,
721 source_requires_privileged_parent=False,
722 ),
723 "tools/rabook_imagepack/tests/convert_integration.sh": ShellPolicy(
724 ShellSecurity.PORTABLE,
725 ShellUsage.ENTRY,
726 ShellDialect.POSIX_SH,
727 executable=False,
728 source_requires_privileged_parent=False,
729 ),
730 "tools/rabook_imagepack/tests/rabook_inspect_integration.sh": ShellPolicy(
731 ShellSecurity.PORTABLE,
732 ShellUsage.ENTRY,
733 ShellDialect.POSIX_SH,
734 executable=False,
735 source_requires_privileged_parent=False,
736 ),
737 "tools/rabook_imagepack/tests/verify_integration.sh": ShellPolicy(
738 ShellSecurity.PORTABLE,
739 ShellUsage.ENTRY,
740 ShellDialect.POSIX_SH,
741 executable=True,
742 source_requires_privileged_parent=False,
743 ),
744 "tools/rabook_viewer/tests/run_corpus.sh": ShellPolicy(
745 ShellSecurity.PORTABLE,
746 ShellUsage.ENTRY,
747 ShellDialect.BASH,
748 executable=True,
749 source_requires_privileged_parent=False,
750 ),
751 "tools/rabook_viewer/tests/run_workspace_test.sh": ShellPolicy(
752 ShellSecurity.PORTABLE,
753 ShellUsage.SOURCED_ONLY,
754 ShellDialect.BASH,
755 executable=False,
756 source_requires_privileged_parent=False,
757 ),
758 "tools/reader_vmem/tests/integration.sh": ShellPolicy(
759 ShellSecurity.PORTABLE,
760 ShellUsage.ENTRY,
761 ShellDialect.BASH,
762 executable=True,
763 source_requires_privileged_parent=False,
764 ),
765}
766
767
768def _policy_from_row(row: ShellPolicyRow) -> tuple[str, ShellPolicy]:
769 """Convert one compact domain row into the canonical typed value."""
770 path, security, usage, dialect, executable, privileged_parent = row
771 return path, ShellPolicy(
772 ShellSecurity(security),
773 ShellUsage(usage),
774 ShellDialect(dialect),
775 executable=executable,
776 source_requires_privileged_parent=privileged_parent,
777 )
778
779
780def merge_policy_tables(
781 base: dict[str, ShellPolicy],
782 *domains: tuple[ShellPolicyRow, ...],
783) -> dict[str, ShellPolicy]:
784 """Merge independently reviewable domains, rejecting duplicate authority."""
785 merged = dict(base)
786 for domain in domains:
787 for row in domain:
788 path, policy = _policy_from_row(row)
789 if path in merged:
790 raise DuplicateShellPolicyError(path)
791 merged[path] = policy
792 return merged
793
794
795SHELL_POLICIES = merge_policy_tables(_BASE_SHELL_POLICIES, CI_POLICY_ROWS, HIL_POLICY_ROWS)
796
797PRIVILEGED_PATHS = frozenset(
798 path for path, policy in SHELL_POLICIES.items() if policy.security is ShellSecurity.PRIVILEGED
799)
800SOURCED_ONLY_PATHS = frozenset(
801 path for path, policy in SHELL_POLICIES.items() if policy.usage is ShellUsage.SOURCED_ONLY
802)