## Source

Both halves appear twice in `TODO`:

- "JS APIs should prevent use of certain GPIO that would break I2C or other protocols"
- "Set and enforce a max program size in both firmware and the uploader UI"

## Current state

- `crates/sb-esp/src/hal.rs` defines `MAX_GPIO`, but there is no reserved-pin map that stops `gpio.write()` from taking a pin used by a module bus or another protocol.
- Upload frames have `MAX_PAYLOAD_LEN`, but there is no maximum program size enforced by firmware or checked by the uploader.

## Acceptance — reserved GPIO

- [ ] Define one reserved-pin map per board/protocol, in one place shared by the runtime, editor and docs.
- [ ] Module-bus and protocol pins cannot be driven through the generic GPIO API.
- [x] Decision: a reserved GPIO conflict is a **hard runtime error**.
- [ ] The runtime returns a typed, user-readable error; the editor surfaces the same conflict before upload where possible.
- [ ] Rust tests cover every reserved pin and a legal pin.

## Acceptance — program size

- [x] Decision: maximum program size is **64 KB**.
- [ ] Encode 64 KB as one shared constant in firmware, uploader and UI.
- [ ] Firmware rejects an oversized upload with a clear error and leaves the previous program intact.
- [ ] The uploader checks the size before flashing, shows the error next to the run/upload control, and does not start a flash it knows will fail.
- [ ] Tests cover max-1, max and max+1 bytes.

- [ ] Update the runtime/API documentation with both limits.


<sub>Generated on _MrBeast_ using _opencode/deepseek-v4.1-flash_ in _ses_e8326e581ffeJviTmSkomwnKES_</sub>


