Skip to content

[FEAT] Pluggable byte-oriented record codec — enable bincode on type-aware data-plane interfaces #155

Description

@lxsaah

Background

The record-value codec today is hard-wired to serde_json::Value. The capability trait RemoteSerialize and the type-erased JsonCodec<T> / SerdeJsonCodec (aimdb-core/src/codec.rs) only model "T ↔ serde_json::Value". The wire envelope, by contrast, is already cleanly pluggable: EnvelopeCodec (aimdb-core/src/session/mod.rs:392) operates on opaque Payload = Arc<[u8]>, with the NDJSON specifics contained in AimxCodec (aimdb-core/src/session/aimx/codec.rs).

So the envelope can be swapped, but the value model cannot — there is no Codec<T, Repr>, JSON is the type. Design doc docs/design/032-M16-aimx-json-codec.md explicitly lists "Custom (non-JSON) AimX wire formats" as out of scope.

Proposal

Generalize the layer-2 record-value codec from "T ↔ serde_json::Value" to a byte-oriented, pluggable Codec<T> (T ↔ bytes), so the serialization format becomes a codec impl behind one seam. Payload = Arc<[u8]> already flows everywhere, so the boundary type is unchanged.

Once the seam exists, bincode becomes a codec impl for compact, fast, schema-stable serialization — usable on interfaces where both peers share the typed contract.

The critical constraint — type-aware interfaces only

bincode is non-self-describing: you cannot decode its bytes without already knowing the exact target type (and its field order/versions). AimDB's interfaces are not uniform:

  • Type-aware — data-plane links between peers that share a Streamable / Linkable data contract; both ends know T. ✅ bincode fits here.
  • Type-agnostic — AimX remote introspection, the MCP server, the dashboard; the peer has no T. ❌ bincode here reintroduces "opaque bytes at the erased boundary" and destroys the typed-edge model.

So this is not "bincode at the interfaces" wholesale — it is "bincode on the interfaces where a shared contract already lives." The self-describing paths must keep a self-describing codec (JSON today; possibly CBOR — see related issue).

Why it's interesting

  • It is the more architecturally meaningful of the two ideas: once the byte-oriented seam exists, JSON, CBOR, and bincode are all just codec impls — self-describing formats on the erased/introspection paths, bincode on the contract-sharing data plane.
  • Compact + fast binary serialization for high-volume, known-type data flows.

Constraints / risks

  • Requires defining where the type-aware boundary is and ensuring bincode is only reachable there (a known-T codec selection, not the type-erased dyn AnyRecord JSON methods).
  • Schema/version coupling: both peers must agree on T's layout — a contract change the JSON path does not impose.
  • Touches the codec capability trait (RemoteSerialize / JsonCodec) and with_remote_access config-time capture.

Scope

Investigation + decision capture only. A design document (next number after 036) will follow if/when this is picked up.

Suggested sequencing

This seam is the enabler. Land it first; the self-describing-IR choice (related issue) then becomes "pick the default self-describing codec impl" rather than a separate rewrite.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions