Widen the slot id to 16 bits so capacity can pass 255
Credential capacity is pinned per variant at up to 700 by the vault
dimensioning study, but the slot id was a u8 across the app, web and
persistence layers: every id above 255 would have aliased onto a live
slot. Widen the id and the counts derived from it to uint16_t through
vault, web, states and ui; TOTP and group ids deliberately stay u8
(their caps stay under 255) and are now pinned by co-located
static_asserts instead of by assumption.
The wire follows: index rows and the row count, and the slot id in the
envelope's authenticated context, become u16 little-endian, growing the
context prefix from 7 to 8 bytes. No version byte moves — the format is
pre-release and every board is reflashed — but the security docs that
quote the prefix byte-for-byte are updated so the audit dossier stays
verifiable against the source.
Adversarial review of the diff found four defects worth naming, all
fixed here:
- promoteAll() held two capacity-sized filename vectors live on the
32 KB vault-worker stack; at the 700-slot pin that is ~78 KB and a
guaranteed overflow on the first SD import or re-key. Both move to
the heap, matching the pattern the rest of the vault already uses.
- The widened staged-filename grammar accepted cred_007.bin as well as
cred_07.bin for the same slot, so an import deleted the canonical
record and wrote a path the repository never opens — silent slot
loss where the previous grammar had failed closed. The grammar is now
canonical-only and lives in one header both readers share.
- DevicePanel kept the last-viewed slot in editCredId_ after BACK, so
the standalone password generator saved into it, blanking that
credential's name, user and url. The id now resets to the invalid-slot
sentinel, and the guard that also made slot 0 unwritable is gone.
- The envelope test asserted the id's new high byte against its own
zero-initialized fixture, so it would have passed against a writer
that never wrote that byte at all.
Verified: native 2843/2843 (including a new wide-capacity suite that
exercises slot 260 end to end), sticks3_debug, cardputer_debug, tdeck
and core2_v13_debug, plus the merge gate — a clean -Werror build at
VAULT_MAX_CREDENTIALS=300, which is what proves no narrowing survives.
Claude-Session: https://claude.ai/code/session_01Q2J5gQSFMTDLVzPUYog51r