Fixed in https://github.com/badbundle/vault-app/pull/616 (merged as 013dccfe).
The new records: VaultItemRecord, with nested OTP, note and encrypted-item details, and VaultTagRecord. They're field-for-field copies of the stored schema in raw form, so even items that wouldn't decode survive a move between stores.
Encoders and decoders: they no longer depend on SwiftData, and now live in VaultStore/Records/. The SwiftData store copies between records and its models, and its behaviour is unchanged.
Tests:
- A schema parity test fails, naming the fields, if the schema and the records drift apart.
- Round-trip tests cover every field and edge case.
- Store tests cover tags, digests and imports.