Enforcing a data structure

I’m making a small note taking application and I really want to use Yjs for the collaborative aspect of it. However I’m stuck on how you can validate the updates sent by clients.

Basically there are projects and each project has cards where users can, for example, type in text. Currently this is all done with a client-server architecture where the server is the source of truth. Clients can update cards and send their updates to the server which will broadcast it to all other clients.

Since Yjs is schema-less I believe this means clients can add arbitrary data to the Y.Doc and the server will just happily add it to it’s own local copy of the Doc and broadcast it. Instead what I want to do is validate the update sent by the client and, only if the update is valid, I want to apply it to the local copy of the doc on the server and broadcast it to everyone else. I want to know how to do this in a nice way.

let Ok(bytes) = general_purpose::STANDARD.decode(update) else { return };
let Ok(update) = Update::decode_v1(&bytes) else { return };
let doc = project_state.doc();
{
    let _ = doc.get_or_insert_map("nodes").observe_deep(|txn, events| {
        for event in events.iter() {
            match event {
                Event::Text(x) => info!("{:?}", x.delta(txn)),
                Event::Array(x) => info!("{:?}", x.delta(txn)),
                Event::Map(x) => info!("{:?}", x.keys(txn)),
                Event::XmlFragment(x) => info!("{:?}", x.delta(txn)),
                Event::XmlText(x) => info!("{:?}", x.delta(txn)),
            }
        }
    });

    let mut txn = doc.transact_mut();
    txn.apply_update(update);
}

This is the current code I have on the server (using Yrs). I was thinking of taking a snapshot of the current document, applying the update, checking if all the changes are valid, and if something is off then reverting back to the old snapshot. This solution seems pretty ugly, like I was expecting maybe you can inspect the update directly to see the things that are being modified and if it’s fishy simply not apply it. Another problem I’m having is how do you check if the update modifies anything on the top-level, like as far as I know I can’t do observe_deep on the whole document. Thanks in advance!

Okay looking around it seems like Yjs isn’t really fit for my problem. It looks like Yjs is meant for situations where every client is trusted, where in my situation I have a central server controlling the document, validating every change every client is doing to make sure it’s not malicious.