Buffer Pipeline (Default Performance Path) โ
Since v1.3.2, FLASH converts documents to FlashBinary buffers at the SDK boundary and keeps them as buffers inside the LSM engine (WAL, memtable, SSTables).
You still write objects. The engine works on bytes.
Why buffers? โ
| Step (old) | Step (new) |
|---|---|
| object โ encrypt object โ serialize โ Buffer | object โ encryptToBuffer โ Buffer |
| Buffer โ deserialize full object โ decrypt | Buffer โ getField โ decrypt partial |
Benefits:
- Fewer allocations on read/write hot paths
- Skip parsing
_blindindex payload on everyfind - SSTable v2 already reads block ranges โ buffers align with that model
- Same zero-knowledge encryption โ crypto unchanged
Developer API (FlashClient) โ
Write path โ
javascript
import { FlashClient } from "flash-zk";
const client = new FlashClient({ secretKey: "key", storagePath: "./data" });
const col = client.collection("users");
// Normal โ buffer conversion is automatic
await col.insertOne({ name: "Ada", email: "ada@example.com" });
// Advanced โ prepare buffer yourself (bulk, streaming, custom pipelines)
const buf = client.encryptToBuffer({ _id: "u1", name: "Ada", email: "ada@example.com" });
await col.raw.insertOne(buf);Read path โ
javascript
// Normal โ returns decrypted objects
const users = await col.find({ name: "Ada" }).exec();
// Advanced โ read raw engine buffer
const raw = await col.raw.findOne({ _id: "u1" });
if (raw) {
const doc = client.decryptFromBuffer(raw);
// or field-level via FlashBinary.getField(raw, "_enc.email")
}FlashRecordCodec โ
Exported from the main package for tools, replication, and custom storage layers.
javascript
import { FlashClient, FlashRecordCodec, FlashBinary } from "flash-zk";
const client = new FlashClient({ secretKey: "key" });
// Encode
const buf = FlashRecordCodec.toBuffer(client, { name: "Test" });
const id = FlashRecordCodec.extractId(buf);
// Decode (skips full _blind parse)
const plain = FlashRecordCodec.decrypt(client, buf);
// Wire transport (remote server)
const wire = FlashRecordCodec.encodeForWire(buf);
const restored = FlashRecordCodec.decodeFromWire(wire);| Method | Description |
|---|---|
toBuffer(client, doc) | Plain doc โ encrypted FlashBinary buffer |
decrypt(client, bufOrObj) | Buffer or legacy object โ plain doc |
extractId(buf) | Read _id without full deserialize |
extractBlind(buf) | Read _blind for indexing |
extractPlain(buf) | Read _plain metadata fields |
encodeForWire(buf) | { _flashRecord: base64 } for HTTP |
decodeFromWire(payload) | Restore buffer from wire JSON |
FlashBinary helpers โ
For engine-level code (SQL engine, Wire protocol, ETL, federation):
javascript
import { FlashBinary } from "flash-zk";
const col = db.collection("items"); // FlashCollection (low-level)
const buffers = await col.find({});
// Decode when you need objects
const docs = FlashBinary.decodeRecords(buffers);
// Or single field without full parse
const email = FlashBinary.getField(buffers[0], "_enc.email");Layer diagram โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Application โ
โ insertOne({ ... }) find() โ objects โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ FlashClientCollection (SDK) โ
โ encryptToBuffer / decryptFromBuffer โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ FlashCollection (engine) โ
โ Buffer in memtable, WAL, SSTables โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Disk (optional) โ
โ .farc WAL ยท .sst segments โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโRemote mode notes โ
When using uri: "flash://host:6742":
- Client encrypts to buffer locally
- Server stores buffer via REST
- Query responses return
_flashRecordbase64 - Client decrypts locally โ server never sees plaintext
insertMany on remote currently performs sequential insertOne calls.
When you still get objects vs buffers โ
| API | Returns |
|---|---|
client.collection().find().exec() | Plain objects (decrypted) |
client.collection().insertOne() | { insertedId, merkleRoot } |
db.collection().find() (FlashDatabase) | Buffer[] |
col.raw.find() (SDK) | Buffer[] |