GSoC 2026 Proposal Draft - Idea 7: Local Note Encryption - keshav0479

yeah, an is_locally_encrypted flag on resources makes sense. without it there's no clean way to tell "encrypted file" from "unreadable file" in the attachment manager.

i also traced a related issue in ResourceService.indexNoteResources() (L82-91) - it parses note.body to extract resource IDs via Note.linkedResourceIds. with a locally encrypted body (JOPLIN_CIPHER:...), that parse returns nothing, which would cause setAssociatedResources to mark all the note's resources as is_associated = 0, eventually orphaning and deleting them. it already skips E2EE-encrypted notes at L82 - locally encrypted notes need the same skip.

for the decrypt lifecycle when a resource reference is removed: NoteResource.associatedNoteIds(resourceId) (L75) returns all currently associated note IDs. joining that with notes.is_locally_encrypted tells us if any remaining note is still encrypted. if none are, decrypt the resource and clear the flag. same fast indexed query, no body scanning.

i'll update section 3.9 to cover the resource flag, the indexNoteResources skip, and the decrypt-on-disassociate lifecycle.