Versioned Decoder Adapter¶
Migration adapter — instantiates Round-Trip Serialization Contract
A decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the upgrade is declared, not hidden.
Payloads outlive the code that wrote them. A save file, a stored document, an event on a long-retention topic — all can be years older than the software now trying to read them. Versioned Decoder Adapter is the layer that bridges that gap: it reads the payload's declared version, then actively transforms the old structure into the current one by running it through an ordered chain of migration steps (v1→v2→v3→…→current), each a small, tested up-conversion. Its defining move is transformation, not negotiation: unlike a scheme that keeps old and new compatible, the adapter takes a genuinely old-shaped payload and rewrites it into today's shape, filling introduced fields, renaming and restructuring, dropping what no longer exists — and, crucially, declaring whatever fidelity that upgrade cannot preserve rather than silently discarding it. It is the "read the past into the present" half of the version policy.
Example¶
A desktop illustration app has shipped for a decade, and its .draw save files span five format versions. Version 1 stored a flat list of shapes; version 3 introduced layers; version 5 replaced RGB color triples with a managed color-profile reference. A user opens a v1 file they made years ago.
The versioned decoder adapter reads the file header, sees format: 1, and runs the migration chain: v1→v2 wraps loose shapes in a default group; v2→v3 promotes groups to layers; v3→v4 renames stroke_px to stroke_width; v4→v5 converts raw RGB into the nearest managed-profile color. Each step is a small function that transforms one version's structure into the next. The file loads into the current editor as if it had been saved yesterday. But the v4→v5 color conversion is lossy — the old raw RGB cannot be perfectly expressed in the new managed profile — so the adapter records a lossiness note the app surfaces to the user ("legacy colors approximated to the current profile") rather than pretending the upgrade was exact. The past opens in the present, honestly.
How it works¶
- Read the version stamp. Every payload declares its format version; the adapter dispatches on it rather than guessing.
- Compose the migration chain. Apply ordered up-conversion steps from the payload's version to the current one; each step is small, individually tested, and reused across every longer chain.
- Reconstruct into the current model. After the final step, hand a current-shaped structure to the normal reconstruction rule, with introduced fields defaulted and removed fields dropped.
- Declare what the upgrade cost. Where a migration cannot preserve a distinction (an approximated color, a collapsed field), record it as an explicit lossiness note instead of silently losing it.
Tuning parameters¶
- Chain vs. direct migration — stepwise v_n→v_{n+1} composition vs. bespoke vN→current jumps. Chaining is maintainable (one step per version) but slower for very old payloads; direct jumps are fast but multiply the paths to test.
- Migration timing — on-read (lazy, payload upgraded when loaded) vs. batch re-encode (eager, whole store rewritten). Lazy is cheap and reversible; eager retires old code sooner but touches everything at once.
- Unknown-version stance — best-effort decode vs. hard refuse for versions newer than the reader. Best-effort keeps things loading; refusing prevents misreading a future format as a familiar one.
- Lossiness verbosity — silent, logged, or user-surfaced approximation notes. More surfacing protects trust; too much noise trains users to ignore it.
When it helps, and when it misleads¶
Its strength is longevity: it lets a format evolve freely while every historical payload still loads, and by keeping each migration step small and tested it makes a decade of format drift maintainable instead of a minefield. It is what separates graceful schema evolution from the archetype's "saves in one version, corrupts in the next" failure.
Its failure mode is migration debt and lossy chains: each step can lose a little fidelity, and composed across many versions those small losses accumulate, so a very old payload may arrive subtly degraded — and an untested step in the chain can corrupt everything downstream of it. The classic misuse is an implicit migration that quietly drops or defaults data without declaring it, so the upgrade looks clean while information is gone. The guarding discipline is to test every step (and representative full chains) with real old fixtures, and to treat any non-preserving step as a declared loss, never a silent one.
How it implements the components¶
version_and_migration_policy— it embodies the policy: version dispatch plus an ordered chain of up-conversion rules that define how old payloads become current ones.deserialization_reconstruction_rule— it owns the decode path for legacy payloads, transforming then reconstructing into the current model.lossiness_declaration— it makes any fidelity a migration cannot preserve explicit, rather than letting the upgrade hide the loss.
It does not resolve schema compatibility by negotiating reader against writer at a service — that is its nearest twin Avro Schema Registry's use of an external_registry_dependency; the adapter instead rewrites the payload itself. It also defines no identity_and_reference_map; preserving shared nodes across the graph is Object-Graph Identity Table's job.
Related¶
- Instantiates: Round-Trip Serialization Contract — supplies the version-migration face of the contract, keeping old payloads readable.
- Consumes: JSON Schema Encoder/Decoder — after up-converting a legacy payload to the current shape, it hands off to a current-version decoder for final reconstruction.
- Sibling mechanisms: Archive Manifest · Avro Schema Registry · Canonical JSON Normalization · JSON Schema Encoder/Decoder · Object-Graph Identity Table · Payload Signature or Hash · Protocol Buffers Message Definition · Round-Trip Fixture Test · XML Schema and Parser
Editorial Notes¶
Form Classification¶
Form family: Control, Automation & Runtime
Rationale: Versioned Decoder Adapter operates as a live operational control that automatically routes, enforces, adapts, or responds during execution because it a decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the upgrade is declared, not hidden.
Independent corroboration: The frozen evidence defines Versioned Decoder Adapter as 'A decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the upgrade is declared, not hidden', so its operative form is Control, Automation & Runtime.
Nearest alternative: Protocol, Workflow & Routine — Versioned Decoder Adapter includes features of a repeatable ordered procedure or handoff sequence that coordinates action, but its defining operation is a live operational control that automatically routes, enforces, adapts, or responds during execution.
Review outcome: Independent reviewer agreement; medium confidence.
Origin Attribution¶
Primary origin: Computer Science & Software Engineering
Origin pattern: Single lineage
Present-day reach: Universal
Rationale: Both independent reviews identify computer science as the historical home of the operation—A decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the upgrade is declared, not hidden.. The retained alternates document formative adjacent traditions; the reach field, not the origin field, carries later applicability.
Related originating lineages:
- Data Science & Analytics — Data science's modeling, validation, and monitoring tradition contributes a separate formative lineage to the mechanism's versioned decoder adapter logic.
- Engineering & Design — Engineering design, reliability, and systems-safety practice supplies a parallel or contributing lineage for the mechanism's defining operation: a decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the….
Review resolution: Both blind reviewers independently place the defining operation—A decode-time layer that reads a payload's version stamp and runs it up a chain of migrations to the current shape — so old payloads keep loading, and any fidelity lost in the upgrade is declared, not hidden.—in computer science. Their queued differences are secondary: alternate_origin_disagreement, origin_mode_disagreement, encyclopedia_synthesis_disagreement. Reviewer A uniquely contributes ['data_science']; reviewer B uniquely contributes ['engineering_design']. I preserve the full evidence-supported union of 2 alternate domain(s), without a numeric cap. origin_mode=single_lineage reflects the more specific lineage judgment in reviewer B's evidence, while domain_reach=universal separately records present-day portability. The affirmative encyclopedia-synthesis finding is preserved, and confidence=high uses the more conservative reviewer level.
Encyclopedia synthesis: The exact catalogued form synthesizes established practice rather than reproducing a single standard historical label.
Review outcome: Reconciled after independent review; high confidence.
Notes¶
The migration chain and a round-trip suite are complementary: chained steps only stay trustworthy if each is exercised against real old fixtures, so a versioned decoder without a fixture test guarding its chain is one refactor away from silently corrupting the oldest payloads it exists to protect.