Summary
SessionInfo (rust/crates/truapi-server/src/host_logic/session.rs) is persisted verbatim as a SCALE blob by encode_persisted_session / decode_persisted_session, with no version tag. The struct carries identity_chat_private_key and device_enc_public_key between identity_account_id and lite_username, so the on-disk field order differs from what any host wrote before #403.
Every blob written by an earlier version fails decode_persisted_session. The pairing host loses its active session and the user has to re-pair.
Repro
Encoding the pre-#403 field order and decoding with the current one fails for every username shape:
both none: Err("Could not decode `SessionInfo::lite_username`:
Could not decode variant byte for `Option`:
Not enough data to fill buffer")
lite only: Err("Could not decode `SessionInfo::identity_chat_private_key`:
Could not decode `Option::Some(T)`:
Not enough data to fill buffer")
both set: Err("Could not decode `SessionInfo::identity_chat_private_key`:
Could not decode `Option::Some(T)`:
Not enough data to fill buffer")
Mechanically: the decoder reads lite_username's Option tag as identity_chat_private_key's. A None username (0x00) makes it consume both new fields as None and then run off the end; a Some username (0x01) makes it try to read 32 bytes of key from the username's length prefix and contents.
Options
- Append new fields at the end of the struct, so old blobs decode with the new fields as
None.
- Or give the blob a leading version byte and decode the old layout explicitly.
- Or keep the break and treat a decode failure as "unpaired", but state that intent in the module docs — currently nothing records that a session reset is expected.
Introduced by #403.
Summary
SessionInfo(rust/crates/truapi-server/src/host_logic/session.rs) is persisted verbatim as a SCALE blob byencode_persisted_session/decode_persisted_session, with no version tag. The struct carriesidentity_chat_private_keyanddevice_enc_public_keybetweenidentity_account_idandlite_username, so the on-disk field order differs from what any host wrote before #403.Every blob written by an earlier version fails
decode_persisted_session. The pairing host loses its active session and the user has to re-pair.Repro
Encoding the pre-#403 field order and decoding with the current one fails for every username shape:
Mechanically: the decoder reads
lite_username'sOptiontag asidentity_chat_private_key's. ANoneusername (0x00) makes it consume both new fields asNoneand then run off the end; aSomeusername (0x01) makes it try to read 32 bytes of key from the username's length prefix and contents.Options
None.Introduced by #403.