Skip to content

Commit 93d048e

Browse files
committed
dir-sim plan V17/V18: deny wins, object types, nested groups, how Stalwart sends; two document regimes
Folds in the HubSPO-rs review on #344: - FullAccess needs a mailbox; SendAs and SendOnBehalf also apply to a distribution group. - group trustees reach users through nested-group expansion, which dir-sim does not have yet (lance-graph W-4); until then only direct members. - a deny from any witness removes the right and is reported; grants alone would fail open. - sending through Stalwart: an identity may only carry its own account's addresses, so SendOnBehalf goes from the trustee's account with Sender set, and SendAs goes to the object's account by master-user impersonation after the V17 check. - V18: record attachments take access from their record; only library and OneDrive files follow the SharePoint model. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G22yT6htkcdyXsihxxXdrg
1 parent 566c27b commit 93d048e

1 file changed

Lines changed: 36 additions & 9 deletions

File tree

‎docs/DIRECTORY-SIMULATION-POC.md‎

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -471,23 +471,44 @@ no-population-intermediate rule.
471471
- **A grant is a relation, not a property.** `(object, trustee, right)`
472472
is its own record, like a membership, and changes by add and remove;
473473
no node carries a list of trustees.
474+
- **The object.** FullAccess needs a mailbox; a grant of it on anything
475+
else is a violation. SendAs and SendOnBehalf also apply to a
476+
distribution group, which has no mailbox of its own.
474477
- **The trustee is a user or a group.** A user holds a right on an
475478
object when it is granted to the user or to any group the user belongs
476-
to, transitively.
479+
to, transitively. This depends on nested-group expansion, which dir-sim
480+
does not have yet: a nested group is held by identity and never
481+
expanded (lance-graph `lance-graph-dir-sim/src/snapshot.rs`, W-4 of
482+
lance-graph's HubSPO-rs handover). Until it lands, a grant to a group
483+
reaches only the group's direct members.
484+
- **Deny wins.** Exchange allows deny entries on FullAccess, and Active
485+
Directory allows them on SendAs. A deny for `(object, trustee, right)`
486+
from any witness, for the user or for any group the user belongs to,
487+
removes the right whatever grants exist. A deny that cancels a grant
488+
is reported, so it is visible rather than silent. Reading grants
489+
without denies would fail open.
477490
- **Each grant carries the witness that asserted it.** LDIF supplies
478491
`publicDelegates` and `msExchDelegateListLink`; Graph supplies none of
479492
the three; the Exchange permission output (`Get-MailboxPermission`,
480493
`Get-RecipientPermission`, `GrantSendOnBehalfTo`) supplies all of them
481494
and is read through the same read-only encoder as V12. Witnesses that
482495
disagree both stay; an absent witness is not a refusal.
483496
- **Consumers.** Spear's mailbox IAM lets a FullAccess trustee read the
484-
mailbox's rows. SendAs and SendOnBehalf gate sending: a consumer that
485-
submits through Stalwart picks the identity, and with SendOnBehalf sets
486-
`Sender` to the trustee.
487-
488-
Not modelled: folder-level permissions (`Add-MailboxFolderPermission`),
489-
calendar delegates, and deny entries, which Exchange allows on
490-
FullAccess.
497+
mailbox's rows. SendAs and SendOnBehalf gate sending, and the consumer
498+
checks the right before every submission; Stalwart does not know about
499+
V17. Stalwart's JMAP submission compares the envelope `mailFrom` with
500+
the identity's address (`crates/jmap/src/submission/set.rs`,
501+
`forbiddenFrom`), and an identity may only carry one of its own
502+
account's addresses (`crates/jmap/src/identity/set.rs`). So:
503+
- **SendOnBehalf** is sent from the trustee's own account and
504+
identity, with `From` set to the object and `Sender` to the trustee.
505+
- **SendAs** cannot be sent from the trustee's account, which has no
506+
identity with the object's address. It is submitted to the object's
507+
own account through master-user impersonation (`object%master`,
508+
`Impersonate` permission), after the V17 check.
509+
510+
Not modelled: folder-level permissions (`Add-MailboxFolderPermission`)
511+
and calendar delegates.
491512
- **V18 — Document access (design, open, 2026-10-10).** Nothing in Spear,
492513
dir-sim or Stalwart decides who may read or change a document (HubSPO-rs
493514
`comms-api-surface.md` §2). SharePoint and OneDrive grant a role (read,
@@ -497,7 +518,13 @@ no-population-intermediate rule.
497518
people); Graph reports these as a drive item's `permissions` with
498519
`roles`, `grantedToV2`, `link` and `inheritedFrom`.
499520

500-
Proposal, not yet decided:
521+
Two regimes, kept apart:
522+
- **Files attached to a record** (a ticket's or a deal's attachments in
523+
HubSPO-rs) take their access from the record they belong to. They are
524+
not SharePoint items and get no grants of their own.
525+
- **Files in a library or a OneDrive** follow the SharePoint model below.
526+
527+
Proposal for the second regime, not yet decided:
501528
- A grant is a relation `(resource, principal, role)`, as in V17. The
502529
resource is a document, folder or drive node with a parent.
503530
- A principal's effective role is the highest role granted to it, or to

0 commit comments

Comments
 (0)