# v1.2.3 — prod build, 2026-08-13

Built from `stage` at `49b79931` (detached), SDK submodule `38743f2f` (on `origin/v2.0.34`,
so the pin is reachable — not an orphaned commit). Both trees clean at build time; the
archive id carries no `-dirty` suffix, so this image is reproducible from those two commits.

Profile is **prod**, confirmed against the binary itself rather than the build flags:
2 prod URLs, 0 dev URLs, 0 `MQTT_DEV_PLAINTEXT_ENABLED` — the dev-only unencrypted
custom-action path is compiled out. Do not confuse this with a bench/dev image.

| file | what it is |
|---|---|
| `app.elf` | **keep this** — the only thing that can decode a fleet crash report from this build |
| `app.map` | symbol/section map for the same image |
| `all-app.bin` | full flash image (serial programming via `bk_loader`) |
| `app_pack.rbl` | OTA package |
| `v1.2.3.rbl` | byte-identical copy of `app_pack.rbl` under the release name |
| `bk7258.config`, `sdkconfig.h` | the exact SDK configuration that produced it |
| `MANIFEST.txt` | version, commits, timestamp, ELF sha256 |

## Decoding a crash from this build

Type-10 (RESTART) payloads carry raw addresses plus `bv` (build id). They are meaningless
without this ELF — decoding against any other image yields confident, wrong function names.

    cd ~/projects/stage-flash
    ./scripts/decode_crash.py --json '<type-10 data object>' --elf \
      ~/projects/lockUltra/firmware-archive/v1.2.3-49b7993/app.elf

`--elf` is given explicitly because the script's own lookup expects the archive to live
under the repo at `firmware-archive/`; this copy is outside it. A crash whose `bv` reads
`49b7993` belongs to this directory.

Integrity check before trusting a decode:

    sha256sum app.elf   # must equal elf_sha256 in MANIFEST.txt
