Keep storage proxies separate from domain records
Meerkat Recall’s domain records flattenBaseFields for API JSON. Do not send those
flattened structs directly through the SurrealDB driver. Use a database proxy
with explicit fields, then convert it with TryFrom.
For example, the entity repository’s EntityDb holds an ID as
surrealdb::sql::Thing, native timestamps as DateTime<Utc>, and each base field
separately. Its conversion constructs the domain BaseFields and validates ID
conversion before returning an Entity.
Read the actual
entity storage proxy and conversion
as the starting point for a new repository. Copying a partial domain struct
into a proxy risks dropping security or provenance fields.
Deserialize native shapes without a JSON intermediate
A custom deserializer must consume the driver’s actual data shape. Converting first toserde_json::Value can lose native record-ID or datetime information.
Use a Serde Visitor with the methods required for the type: string, map, or
native enum access.
A map visitor is not a replacement for visit_enum. The current
record ID deserializers
show how Meerkat Recall handles the supported native and string representations.
Reject unknown representations explicitly rather than guessing a value.
When changing a deserializer, test both the public JSON representation and a
round trip through the in-memory SurrealDB backend. A JSON-only test does not
exercise the native driver boundary.
Reject missing mandatory data
Do not replace a missing creation timestamp with the current time or a missing space ID with an empty string. That would turn an invalid stored record into apparently valid knowledge under the wrong history or scope. Use required proxy fields where absence should fail deserialization. If a compatibility projection needs optional fields, validate them during conversion.StorageError::DataIntegrityError takes a message string:
Project raw native values
Keep timestamps native until after storage conversion:time::format(created_at, ...) in that projection returns a string where
a native timestamp is expected. Format for display only after the Rust value
has been decoded and validated.
Verify a storage-boundary change
A focused repository test should establish the properties affected by the change:- A create/read round trip preserves IDs, timestamps, security, provenance, and subject scope.
- Invalid mandatory data returns an explicit error.
- Supported native and JSON representations deserialize consistently.
- Existing space isolation and soft-delete filtering still hold.
