nx_battery_safety.nx
buildroot/runtime/nx_battery_safety.nx
about
nx_battery_safety.nx -- BMS substrate (Captain Moroni Phase M2).
Per [[feedback-captain-moroni-doctrine]]: "HARD CEILING on commanded
charge/discharge rates. Substrate REFUSES to compile code that
bypasses thermal limits. Refuses microcode that disables BMC
overcurrent protection. ANY commanded thermal-runaway condition
triggers compile-time refusal + substrate alert."
THE HEZBOLLAH-PAGER PRIMITIVE. September 2024 attack used compromised
firmware to command battery into thermal runaway as an explosive
trigger. Per Captain Moroni: substrate refuses code patterns that
could weaponize a battery. Not policy — STRUCTURAL refusal.
Safety envelope (operator can NEVER bypass without twin-key):
- max_charge_rate_q10: ceiling on commanded charge mA
- max_discharge_rate_q10: ceiling on commanded discharge mA
- max_cell_temp_milli_C: hard ceiling on commanded thermal target
- min_cell_voltage_mv: floor (under-voltage protection)
- max_cell_voltage_mv: ceiling (over-voltage protection)
Any nx_battery_command that violates these is REFUSED at this layer.
The caller would normally pass through nx_intent_check_operation
first (NX_OPK_COMMAND_BATTERY requires Defensive intent); even with
Defensive intent, the safety ceilings hold.
Composes:
nx_intent -- caller must declare Defensive intent
nx_evict_journal -- every refused command logged loudly
nx_vitals -- physical instrumentation can spot real-world drift
from declared safety envelope
V1 ships:
- struct NxBatterySafetyEnvelope (per-cell-pack safety limits)
- 5 sealed command kinds (CHARGE/DISCHARGE/REST/CALIBRATE/THERMAL_TARGET)
- validate_command predicate -- substrate refuses unsafe asks
- thermal_runaway_pattern detector (3+ rising-thermal commands
in N seconds = explicit refusal + alert)
dependencies 3 imports · 4 importers
imports: nx_syscalls.nxnx_tier.nxnx_intent.nx
imported by: nx_batt_recondition.nxnx_batt_recondition_test.nxnx_battery_safety_test.nxnx_captain_moroni_compose_test.nx
structs
| 64 | struct NxBatterySafetyEnvelope |
| 81 | struct NxBatteryCommandLog |
| 88 | struct NxBatteryCommandKindEntry |
consts
| 45 | const NX_BC_CHARGE: nx_int = 0 |
| 46 | const NX_BC_DISCHARGE: nx_int = 1 |
| 47 | const NX_BC_REST: nx_int = 2 |
| 48 | const NX_BC_CALIBRATE: nx_int = 3 |
| 49 | const NX_BC_THERMAL_TARGET: nx_int = 4 |
| 50 | const NX_BC_N_KINDS: nx_int = 5 |
| 54 | const NX_BS_OK: nx_int = 0 |
| 55 | const NX_BS_REFUSED_RATE_CEILING: nx_int = 1 |
| 56 | const NX_BS_REFUSED_VOLTAGE_CEILING: nx_int = 2 |
| 57 | const NX_BS_REFUSED_THERMAL_CEILING: nx_int = 3 |
| 58 | const NX_BS_REFUSED_THERMAL_RUNAWAY: nx_int = 4 // pattern detected |
| 59 | const NX_BS_REFUSED_BAD_INTENT: nx_int = 5 |
| 60 | const NX_BS_REFUSED_BAD_KIND: nx_int = 6 |
| 94 | const NX_BS_LOG_ENTRY_BYTES: nx_size = 24 |
functions
| 96 | func nx_bc_kind_is_valid(k: nx_int) -> nx_int |
| 102 | func nx_battery_safety_envelope_new(pack_id: nx_int, |
| 120 | func nx_battery_command_log_new(capacity: nx_size) -> *NxBatteryCommandLog |
| 130 | func _bs_log_at(l: *NxBatteryCommandLog, idx: nx_size) -> *NxBatteryCommandKindEntry called by 1: nx_battery_validate_command |
| 141 | func nx_battery_validate_command(env: *NxBatterySafetyEnvelope, called by 4: nx_recondition_runmainmainmain calls 3: nx_intent_check_operationnx_bc_kind_is_valid_bs_log_at |
| 217 | func nx_battery_envelope_ceiling(env: *NxBatterySafetyEnvelope, kind: nx_int) -> nx_size called by 1: main |