Signing Ops for Authorization / Security
I have just recently started learning about CRDTs and Encryption so I am kind of out of my depth here. But I would hope to be able to secure my data operations at the root level of Loro by signing ops/commits, then before importing using the new tryImport to validate if the signor is allowed to edit the doc by comparing the public key to a list of userIDs.
Signing Ops is supported via doc.subscribePreCommit(listener) - Modify commit options before processing:
This hook is particularly useful because doc.commit() is often invoked implicitly in various methods such as doc.import, doc.export, doc.checkout, and doc.exportJsonUpdates. Without this hook, users attempting to add custom messages to each commit might miss these implicit commit triggers.
const doc = new LoroDoc();
doc.setPeerId(0);
doc.subscribePreCommit((e) => {
e.modifier.setMessage("test").setTimestamp(Date.now());
});
doc.getList("list").insert(0, 100);
doc.commit();
expect(doc.getChangeAt({ peer: "0", counter: 0 }).message).toBe("test");
Advanced Example - Creating a Merkle DAG:
const doc = new LoroDoc();
doc.setPeerId(0);
doc.subscribePreCommit((e) => {
const changes = doc.exportJsonInIdSpan(e.changeMeta);
expect(changes).toHaveLength(1);
const hash = crypto.createHash("sha256");
const change = {
...changes[0],
deps: changes[0].deps.map((d) => {
const depChange = doc.getChangeAt(idStrToId(d));
return depChange.message;
}),
};
hash.update(JSON.stringify(change));
const sha256Hash = hash.digest("hex");
e.modifier.setMessage(sha256Hash);
});
doc.getList("list").insert(0, 100);
doc.commit();
expect(doc.getChangeAt({ peer: "0", counter: 0 }).message).toBe(
"2af99cf93869173984bcf6b1ce5412610b0413d027a5511a8f720a02a4432853",
);