Calendars and address books have been shareable since JMAP Sharing went in. Files never was — though Stalwart treats file storage as a first-class thing to share, and ihasmail has carried the types for it all along. FilesRights and FileNode.shareWith were already declared; what was missing was asking for the property, offering the dialog, and saying so in the list.
Checked against live 0.16.19 first
Read-only, because building a picker against a mock that agrees with you proves nothing:
FileNode/get returns shareWith, and myRights carries all six rights — mayShare among them, true on one's own nodes. The menu entry has a real right to gate on, unlike folder sharing, which is offered ungated because MailboxRights has no such right.
Principal/query answers now that allowDirectoryQueries is on: six individuals, no groups.
ShareNotification/get is implemented. Worth knowing for later; nothing here reads it yet.
Also learned, and relevant to anyone touching the Files queries: filter: { parentId: null } is refused with a request-level HTTP 400 that kills every method call in the request, not just that one. files.ts already uses isTopLevel: true for the root and is fine — but a batched query per tree level would take the whole pane down with it.
The editor preset stops short on purpose
Read, add files, edit contents — and no further. Rename and delete stay with whoever shared the folder: someone given a folder to work in should not be able to rename the thing they were given, or delete it out from under the person who shared it. Both are still there to tick by hand.
One finding earned its own test
Stalwart answers shareWith as {} for a node shared with nobody, not null — every unshared node in a live account came back that way. A truthiness test on the property is true for every node the server has ever returned, so a badge driven by one reports the entire account as shared while being, technically, about the right property. isShared counts keys, and the test says why.
Verified
Against the mock, end to end: sharing Documents with a principal as Editor persists mayRead, mayAddChildren and mayModifyContent and nothing else; the badge appears on that folder and not on the file beside it; re-opening shows the saved rights rather than an empty form, which is what proves fileNodeProps is really asking for the property.
npm run typecheck clean; 297 web and 77 server tests pass, four of them new.
Calendars and address books have been shareable since JMAP Sharing went in. Files never was — though Stalwart treats file storage as a first-class thing to share, and ihasmail has carried the types for it all along. `FilesRights` and `FileNode.shareWith` were already declared; what was missing was asking for the property, offering the dialog, and saying so in the list.
### Checked against live 0.16.19 first
Read-only, because building a picker against a mock that agrees with you proves nothing:
- `FileNode/get` returns `shareWith`, and `myRights` carries all six rights — `mayShare` among them, true on one's own nodes. The menu entry has a real right to gate on, unlike folder sharing, which is offered ungated because `MailboxRights` has no such right.
- `Principal/query` answers now that `allowDirectoryQueries` is on: six individuals, no groups.
- `ShareNotification/get` is implemented. Worth knowing for later; nothing here reads it yet.
Also learned, and relevant to anyone touching the Files queries: `filter: { parentId: null }` is refused with a **request-level HTTP 400** that kills every method call in the request, not just that one. `files.ts` already uses `isTopLevel: true` for the root and is fine — but a batched query per tree level would take the whole pane down with it.
### The editor preset stops short on purpose
Read, add files, edit contents — and no further. Rename and delete stay with whoever shared the folder: someone given a folder to work in should not be able to rename the thing they were given, or delete it out from under the person who shared it. Both are still there to tick by hand.
### One finding earned its own test
Stalwart answers `shareWith` as `{}` for a node shared with nobody, not `null` — every unshared node in a live account came back that way. A truthiness test on the property is true for every node the server has ever returned, so a badge driven by one reports the entire account as shared while being, technically, about the right property. `isShared` counts keys, and the test says why.
### Verified
Against the mock, end to end: sharing Documents with a principal as Editor persists `mayRead`, `mayAddChildren` and `mayModifyContent` and nothing else; the badge appears on that folder and not on the file beside it; re-opening shows the saved rights rather than an empty form, which is what proves `fileNodeProps` is really asking for the property.
`npm run typecheck` clean; 297 web and 77 server tests pass, four of them new.
Nothing was written to the live account.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
**Merged** 2026-08-27 as coffey-labs/ihasmail@fb789bc36f44
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Calendars and address books have been shareable since JMAP Sharing went in. Files never was — though Stalwart treats file storage as a first-class thing to share, and ihasmail has carried the types for it all along.
FilesRightsandFileNode.shareWithwere already declared; what was missing was asking for the property, offering the dialog, and saying so in the list.Checked against live 0.16.19 first
Read-only, because building a picker against a mock that agrees with you proves nothing:
FileNode/getreturnsshareWith, andmyRightscarries all six rights —mayShareamong them, true on one's own nodes. The menu entry has a real right to gate on, unlike folder sharing, which is offered ungated becauseMailboxRightshas no such right.Principal/queryanswers now thatallowDirectoryQueriesis on: six individuals, no groups.ShareNotification/getis implemented. Worth knowing for later; nothing here reads it yet.Also learned, and relevant to anyone touching the Files queries:
filter: { parentId: null }is refused with a request-level HTTP 400 that kills every method call in the request, not just that one.files.tsalready usesisTopLevel: truefor the root and is fine — but a batched query per tree level would take the whole pane down with it.The editor preset stops short on purpose
Read, add files, edit contents — and no further. Rename and delete stay with whoever shared the folder: someone given a folder to work in should not be able to rename the thing they were given, or delete it out from under the person who shared it. Both are still there to tick by hand.
One finding earned its own test
Stalwart answers
shareWithas{}for a node shared with nobody, notnull— every unshared node in a live account came back that way. A truthiness test on the property is true for every node the server has ever returned, so a badge driven by one reports the entire account as shared while being, technically, about the right property.isSharedcounts keys, and the test says why.Verified
Against the mock, end to end: sharing Documents with a principal as Editor persists
mayRead,mayAddChildrenandmayModifyContentand nothing else; the badge appears on that folder and not on the file beside it; re-opening shows the saved rights rather than an empty form, which is what provesfileNodePropsis really asking for the property.npm run typecheckclean; 297 web and 77 server tests pass, four of them new.Nothing was written to the live account.
🤖 Generated with Claude Code
Merged 2026-08-27 as coffey-labs/ihasmail@fb789bc36f
Rebuilt from: git history, session transcript.