wim
Joined 18 years ago
Joined 18 years ago
Because of end-to-end-encryption and privacy/ownership concerns, we can't run plugin code on a server node somewhere. But for some types of apps, server-side extensions alone also feel too restrictive. An advantage of a malleable app over just one-shotting a completely custom app (and to be clear I think both will be popular!) is that extending and customizing something is often exactly what you want vs starting over, but you can't really do that when you can't do things like deeply customizing the UI. So you can just ask a (local) agent "add me this functionality" and it will likely be possible.
It's still sandboxed inside the browser though, so this way you can do things like permissions, allowing admins to restrict who installs team plugins and so on (which is also important for malleable multiplayer apps).
We can't just merge any type of operation by replaying unconditionally, because that can cause tree cycles for example. Like the linked list certain operations can be valid locally for an offline client, but not globally in the converged order.
Our sync engine distinguishes between different types of operations: unconditional operations and guarded operations.
Unconditional operations can't violate structural/data-model invariants. For example SetCompleted(task_guid, true). Simple last-writer-wins.
Guarded operations can mutate topology, like InsertMove(node_guid, parent_guid, after_guid). These are checked against the current state, not the state when they were created. During replay we first revert optimistic local operations and replay the incoming canonical operations in order. The mutator function for each operation validates the current state before applying it and if it would violate a condition (for example by creating a cycle because another client made another move in the meantime) it is deterministically rejected. In our case we also have an authoritative server so we can also use the same guarded operations for conditions beyond data structure, like permissions, so the AddUser(workspace_guid, user_guid) mutator function can check permissions state first for example.
https://github.com/chrislgarry/Apollo-11/blob/master/Comanch...
# THE POSITION OF THE MOON IS STORED IN THE COMPUTER IN THE FORM OF # A NINTH DEGREE POLYNOMIAL APPROXIMATION WHICH IS VALID OVER A 15 # DAY INTERVAL BEGINNING SHORTLY BEFORE LAUNCH. THEREFORE THE TIME # INPUT BY THE USER SHOULD FALL WITHIN THIS 15 DAY INTERVAL.
Better be back home in 15 days! ;)
If that passes that's not just EU funds being misused but the EU directly mandating spyware on a continental scale!
With structured apps (task managers, outliners) you lose the illusion of editing plain text, but plain text alone lacks things like structure, links, dates, and collaboration. We've spent the last few years building an editor completely from scratch to keep the ease of text editing while adding planning and structure.
I posted a little clip [1] of development on a multiplayer IDE for tasks/notes (local-first+e2ee), and a lot of people asked if it was native, rust, GPU rendered or similar. But it's just web tech.
The only "secret ingredients" here are using plain ES6 (no frameworks/libs), having data local-first with background sync, and using a worker for off-UI-thread tasks. Fast web apps are totally doable on the modern web, and sync engines are a big part of it.
Co-founder Papyrs. Wrote hobby OS, TriangleOS.
Feel free to contact me, wim at stunf.com or https://x.com/wcools/