The delete preview for a document folder tells a member something about documents they are not allowed to see. This closes the two follow-ups promised in the #989 merge comment on 2026-09-04 ("the impact snapshot hashing invisible documents (and the 409 arriving before the 403), and unfile running into the lock window"), which have had no ticket until now.
The leak
GET /documents/folders/:id/delete-impact (server/routes/documents.js:706) counts only the documents the caller can see, but builds its snapshot - the value the delete later has to match - over every document in the subtree and its links. The snapshot is an HMAC, so it reveals no ids or counts. It does change whenever an invisible document in that subtree is added, removed or linked to a task or event. Asking twice therefore tells a member whether something happened to documents that are private to someone else. can_delete_documents: false already says that invisible documents exist, and a test pins that deliberately; the activity signal goes beyond it.
Decided
- The snapshot covers only what the caller can see. The safety does not depend on the hash: at commit time the delete still refuses (403) unless everything in the subtree is visible to and manageable by the caller, and if a document becomes visible in between, the visible set changes and the delete answers 409
FOLDER_CONTENT_CHANGED as today.
- That 403 is translated in the client. In the race it can now reach the dialog, where today it would show the raw English server text.
unfile and the lock window (overlapsActiveDeletion, documents.js:927-929) - the second promised follow-up - belongs in the same change.
Tests
Red before the fix: two preview requests with an invisible document added, changed or linked in between return the same snapshot; the race (invisible document added after the preview) ends in a translated 403, and a visible document added after the preview still ends in 409.
Refs #989
The delete preview for a document folder tells a member something about documents they are not allowed to see. This closes the two follow-ups promised in the #989 merge comment on 2026-09-04 ("the impact snapshot hashing invisible documents (and the 409 arriving before the 403), and unfile running into the lock window"), which have had no ticket until now.
The leak
GET /documents/folders/:id/delete-impact(server/routes/documents.js:706) counts only the documents the caller can see, but builds itssnapshot- the value the delete later has to match - over every document in the subtree and its links. The snapshot is an HMAC, so it reveals no ids or counts. It does change whenever an invisible document in that subtree is added, removed or linked to a task or event. Asking twice therefore tells a member whether something happened to documents that are private to someone else.can_delete_documents: falsealready says that invisible documents exist, and a test pins that deliberately; the activity signal goes beyond it.Decided
FOLDER_CONTENT_CHANGEDas today.unfileand the lock window (overlapsActiveDeletion,documents.js:927-929) - the second promised follow-up - belongs in the same change.Tests
Red before the fix: two preview requests with an invisible document added, changed or linked in between return the same snapshot; the race (invisible document added after the preview) ends in a translated 403, and a visible document added after the preview still ends in 409.
Refs #989