Records
Store structured app records with the same encrypted envelope model.
Use mesh.records for JSON-serializable app state that should use the same encrypted envelope, CID, and proof model as files.
Records are best for preferences, private metadata, drafts, profile fragments, workflow state, and other structured values your app wants to version or retrieve by CID.
import { meshkit } from "@meshkit/meshkit";
type Preferences = {
theme: "light" | "dark";
retries: number;
};
const mesh = await meshkit();
const saved = await mesh.records.put<Preferences>("user-preferences", {
theme: "dark",
retries: 2,
});
const preferences = await mesh.records.get<Preferences>(saved.cid);
console.log(saved.cid, preferences.theme);Files Versus Records
| Use files when... | Use records when... |
|---|---|
| The payload is a document, image, export, upload, or binary value | The payload is JSON-like application state |
| You care about filenames and content types | You care about record names and TypeScript shapes |
| The value may be streamed or downloaded | The value should be parsed back into an object |
Both APIs encrypt before storage and return a CID. The difference is how your application thinks about the payload.
How Records Work
records.put<T> JSON-encodes the value, encrypts the encoded bytes, stores the envelope, and returns a MeshFile. records.get<T> reads by CID, decrypts, and parses the JSON back into T.
The generic type parameter is for TypeScript ergonomics. MeshKit does not validate a runtime schema for you. Validate user-provided data before storing it and after reading it if the shape matters.
API
await mesh.records.put<T>(name, value, options);
await mesh.records.get<T>(cid);| Parameter | Type | Required | Description |
|---|---|---|---|
records.put<T>(name, value, options) | string, T, PutOptions | Yes for name and value | Stores JSON as an encrypted MeshKit object |
records.get<T>(cid) | string | Yes | Decrypts and parses the record |
options.recipients | string[] | No | Wraps the data key for additional identities |
options.metadata | Record<string, unknown> | No | Authenticated metadata for app routing, not secrets |
What To Persist
- Record CID
- Logical record name
- App schema or version
- Owner, workspace, or tenant ID
- Proof summary if audit matters
Common Mistakes
- Treating the TypeScript generic as runtime validation.
- Storing secrets in metadata instead of inside the encrypted record value.
- Overwriting an application pointer without keeping the previous CID when users need history.
- Assuming a record name is globally unique. The CID is the stable retrieval handle.
Failure Modes
| Symptom | Likely cause | Action |
|---|---|---|
| JSON parse fails | The CID points to non-record content or incompatible schema | Confirm the CID and migrate or validate schema |
key_unwrap_failed | Current identity is not authorized for that envelope | Open with the right identity or share the record |
| Record cannot be found later | App did not persist the returned CID | Store CIDs in your application database |
| Works locally but not in production | Provider bytes exist but MeshKit metadata is missing | Validate the metadata service and provider config |
Production Notes
- Treat record schemas as application contracts. MeshKit stores encrypted bytes; it does not manage schema migrations.
- Keep only routing-safe values in metadata.
- Persist current and previous CIDs when users need rollback, history, or audit.
- Use sharing or capabilities when another identity needs access.
Next Steps
- Store binary content with Files.
- Share a record or file with Sharing.
- Learn the envelope model in Envelope encryption.