Suppose a user imports a project file containing a number larger than JavaScript can represent exactly as an ordinary number. The editor parses it, changes a title, and saves by serializing the in-memory object.
The title change may be correct. The save may still have changed another value without anyone touching it.
This is the persistence boundary between the model you work with and the carrier you were given.
Meaning and text are different promises
Parsing answers a question like: “Can the application understand this input as a project?” A typed model answers: “Which fields does the application know how to edit?” Exact preservation asks a third question: “Can the application keep the user’s original representation where it does not own a change?”
These are not interchangeable.
JSON such as 9007199254740993 can become a rounded JavaScript number when parsed. Serializing the parsed value cannot recover the original digits. Even where values remain equivalent, a serializer may alter whitespace, key order, or unknown fields. Whether that matters depends on the contract. A source formatter may care about lexical form; an editor may need to preserve opaque extension fields; a schema migration may intentionally normalize a document.
The mistake is not using a model. The mistake is silently treating a model as a lossless copy of an input it does not fully represent.
Keep a carrier where the boundary needs one
WorldScript Studio’s restore and import paths carry admitted source alongside the editable model. The carrier is not automatically trusted. It is admitted only after the restore or import has passed the relevant identity and schema checks. When the application later saves a replacement, it uses the admitted carrier as the starting point and overlays fields the application owns.
That lets the editor change what it understands while retaining data outside its ownership boundary. Tests in the #840 lineage use large numeric values and opaque fields to exercise that distinction.
This is a boundary-specific tool, not a reason to avoid validation. The application still needs to decide whether an input is supported, whether the current project authority may accept it, and whether the carrier still belongs to the project lifetime being replaced.
Storage changes what “exact” can mean
On a filesystem, the application can preserve and write the original text. In IndexedDB, the relevant stored value is structured data. Those adapters cannot promise identical byte-level behavior because they do not store the same representation.
That changes how the system should describe its guarantee. “The filesystem restore path preserves admitted text” is a testable statement. “The application preserves every project byte in every storage adapter” is not supported by that implementation.
A useful design names the representation at each edge:
- Input text: the user’s supplied bytes or characters.
- Admitted carrier: the validated text or stored structured value kept for preservation.
- Editable model: the normalized fields the application operates on.
- Egress output: a deliberate projection containing owned edits and portable data.
- Persisted value: the representation chosen by the active storage authority.
Once these are explicit, it becomes possible to ask which edge is allowed to normalize data.
Do not let “round trip” hide the policy
A parse/stringify test may pass while proving only that the resulting document is valid JSON. It does not prove that unknown fields, large numeric lexemes, or the exact source representation survived.
Conversely, a byte-for-byte test is not always the right criterion. If the product intentionally removes machine-local metadata from an export, exact equality would encode the wrong contract. Tests should assert the policy: preserved fields remain, owned edits appear, prohibited metadata is absent, and unsupported inputs fail closed.
The practical lesson is simple: preserve the richest representation your boundary needs, keep it bound to the authority that admitted it, and make every transformation explicit. Models make data usable. Carriers make specific preservation promises possible. A sound editor knows which job each one is doing.
Continue reading
Next in Engineering for No-Loss Data Integrity: Safe Snapshot Restore Under Project Replacement applies the same preservation rules when stored state replaces the active project.
Practical extension: write down the fidelity contract
Before choosing a persistence representation, state what “preserve” means for this boundary. There are at least three different contracts:
- Semantic preservation: parse and serialize may change formatting as long as the supported meaning is unchanged.
- Text preservation: retain characters, ordering, and user-authored formatting where the product promises that surface.
- Byte preservation: retain the exact carrier when signatures, unknown fields, encoding, or unsupported extensions must survive.
These contracts can coexist. Keep a parsed model for editing and an original carrier for lossless round trips. On export, choose deliberately between regenerating from the model and forwarding preserved source material. Never claim byte equality because a parse/serialize test happened to pass on ordinary fixtures.
Add adversarial fixtures at the boundary: large integers, duplicate or unknown fields, unusual whitespace, Unicode normalization, line endings, and values the editor does not understand. Compare the exact expected output only where byte identity is the promise; otherwise assert the semantic invariants and document allowed normalization. For browser-backed state, also test an aborted write and quota failure. MDN documents that IndexedDB requests and transactions can fail and that browser-managed storage is quota-bound: IndexedDB, storage quotas.
Top comments (0)