Project 33 is intended for inert bench validation, simulation, and supervised educational testing. Treat any live propulsion or ignition work as a separate safety-reviewed activity under local law, launch-site rules, and qualified supervision. Nothing in this repository, including a passing CI run, a clean audit, or an evidence packet, authorizes live propulsion or flight activity.
| ID | Gate | Where | Behavior | Source checked by tests | Bench evidence |
|—|—|—|—|—|—|
| G-01 | Physical arming switch | Launcher | Leaving SAFE requires the switch; releasing it from any other state aborts to SAFE. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-02 | Rocket readiness handshake | Launcher + rocket | Launcher enters READY only after the rocket reports READY within 8 s; otherwise it aborts. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-03 | Heartbeat timeout | Launcher | READY aborts if rocket telemetry stops for 2 s. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-04 | Dashboard launch disabled by default | Launcher | UDP launch is rejected with CMD_REJECT:dashboard_launch_disabled unless firmware is rebuilt with the opt-in. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-05 | Dashboard launch requires READY | Launcher | Even with the opt-in, UDP launch is accepted only in READY. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-06 | Dashboard source check | Launcher | Commands are ignored unless they come from the address that sent the shared-token HELLO. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-07 | Physical launch hold | Launcher | The launch button must be held for 1 s with the switch still armed. | Firmware/Launcher/src/main.cpp | NOT MEASURED |
| G-08 | Rocket ARM requires IDLE and a healthy IMU | Rocket | ARM is refused (and now reported) otherwise. | Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-09 | Rocket IGNITE requires ARMED and a healthy IMU | Rocket | IGNITE is refused (and now reported) otherwise. | Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-10 | Rocket IGNITE requires the deploy flag | Rocket | IGNITE is refused unless the deploy timer has fired; see discrepancy D-017 for the ordering question. | Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-11 | Deploy trigger requires a non-IDLE state | Rocket | Handling an unarmed rocket cannot fire the deploy output. | Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-12 | Forced ignition is bench-build only | Rocket | IGNITE_FORCE exists only when BENCH_MODE is defined; the committed build does not define it. | Firmware/Rocket/platformio.ini
Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-13 | Refusals and aborts are logged | Rocket + launcher + dashboard | Rocket refusals travel over UART as CMD_REJECT lines; the launcher forwards them and its own ABORT reasons to the dashboard CSV. | Firmware/Launcher/src/main.cpp
Firmware/Rocket/src/main.cpp | NOT MEASURED |
| G-14 | Bounded controller gains | Launcher + rocket | PID values outside 0-10 or malformed are rejected on both boards. | Firmware/Launcher/src/main.cpp
Firmware/Rocket/src/main.cpp | NOT MEASURED |
Generated from evidence/safety_gates.json. tests/test_firmware_safety.py fails if any gate’s source text changes. Source inspection shows the gate is implemented; it does not show the hardware behaves that way.
Deterministic interlocks live in firmware and stay there. The rocket’s IGNITE path additionally requires the deploy flag, which is set only by a >15 g event while not IDLE; on the bench this acts as an extra interlock, and its intended ordering is an open design question (D-017). Do not remove or reorder any gate without a separate safety review.
ENABLE_DASHBOARD_LAUNCH.SAFE before connecting any actuator.session.json, commands.csv); declare it and build a passport before citing it.READY.SAFE and an ABORT: row is logged.CMD_REJECT:dashboard_launch_disabled is logged; enable it only for a separately reviewed inert test.session.json records a clean close, then run python -m evidence session declare and session passport.