So I actually have backtracked in my thoughts regarding the option gated Note save / load being an issue after having some discussion on the other candidate’s proposal. I’m still trying to figure out potential implementation concerns with conflict resolution, but this is what I wrote on the other thread GSoC 2026 Proposal Draft - Idea 7: Local Note Encryption - keshav0479 - #12 by mrjo118 :
I think I may have been getting confused when looking at a solution to the sync with old client issue.
I think the original option gated Note save / load approach would actually work to the same effect as a thin layer outside of it, but without requiring code duplication. The way you described how it would work in the option gated section in your proposal is clearer than in the proposal of the other candidate, and I think aside from a couple of exceptions, that approach works overall, providing that you consider all save and load flows for the relevant UI which enables the option. A particular example to watch out for is in Note.tsx there is some logic which reloads the note when editorNoteReloadTimeRequest has changed, so missing enabling the option gate for that route could result in corruption of the note, due to it not being decrypted on load.
In terms of the exceptions:
When serialising / deserialising the server item, loading / saving of the note will not use option gated paths, but instead there should be a separate function to move copy transfer the encrypted cipher between the local_encryption_cipher and and the body on the server item, and additionally the logic to add or remove the JOPLIN_CIPHER: prefix and toggle the is_locally_encrypted flag when appropriate for a server item from an old client
The other exception is with the conflict resolution. I initially thought this did not need to be handled, but actually there are some additional considerations here which I’ll cover later
Would you agree that this approach is actually fine?