Skip to content

fix(sharing): show folder access when sharing an item and accept it without extra filing - #317

Merged
novoj merged 1 commit into
devfrom
fix/share-acceptance
Oct 31, 2026
Merged

novoj merged 1 commit into
devfrom
fix/share-acceptance

Conversation

@novoj

@novoj novoj commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Problem

An owner shared a folder with a colleague and also shared one recording of that folder directly. The colleague attached the folder and, because accepting the direct invitation required filing, filed the recording into another folder of their own. The recording then showed twice in their tree. The owner's share dialog had not shown that the colleague already saw the recording through the folder: it and the copy-link popover counted direct invitations only.

Change

Rulings R1–R4 (all option a), recorded in documentation/adr/2026-10-31-share-acceptance-with-existing-folder-access.md:

  • R1, owner: the share dialog shows who sees the item through a shared folder (grouped by folder, "Already sees it through {folder}" in search) and offers no direct invite for them; inviteToItem skips them. Only the folder owner gets "Manage folder sharing". Copy link is never blocked; the popover and the header count distinct people across direct and folder access.
  • R2, receiver: an invitation for an item already visible through a folder says so and is accepted with one click, without filing.
  • R3: ordinary invitations still require filing into an own folder; the dialog explains what the receiver gets and why.
  • R4: filing elsewhere stays possible ("File elsewhere too…") and shows the item in both places; the banner can remove that extra filing again.

Server: GET /api/items/[id]/shares adds folderAudience; listMyInvitations adds the receiver's own accepted folder paths; accept/file may omit folderId only when such a path exists, rechecked inside the share transaction. outgoingItemShareCondition reuses the same audience relation. One ReceivedItemDialog body serves acceptance and later filing for recordings and mail.

No schema change, no env or deploy change.

Testing

  • biome check, tsc --noEmit clean.
  • vitest run --changed origin/dev --no-file-parallelism with Postgres 16: 6454 passed, 82 skipped (Keycloak).
  • New src/tests/sharing/share-acceptance.integration.test.ts (19 cases: both item kinds, own and foreign folders, pending/accepted/inactive recipients, invitation suppression, local names, ownership isolation, revoked paths, unfiling) and extended sharing UI suites.
  • Read-only Codex cross review: one finding (created folders stayed dialog-local), fixed.

Relates to #260.

…ithout extra filing

An owner could invite a colleague directly to an item the colleague already
saw through a shared folder, because the share dialog and the copy-link
popover counted direct invitations only. Accepting that invitation required
filing it into one of the receiver's own folders, so the item showed up
twice in the receiver's tree.

Owner side:
- GET /api/items/[id]/shares also returns the folder audience: the folder
  owner and pending or accepted folder receivers, labelled with the item
  owner's own folder or attachment name.
- The share dialog groups people by folder, labels them in search, offers no
  direct invite for them and links to the folder's sharing (folder owner
  only). inviteToItem skips them.
- Copy link is never blocked. The popover and the header count distinct
  people across direct and folder access.

Receiver side:
- Invitations list the receiver's own accepted folder paths to the item.
- Accept without a folder is allowed only when such a path exists, rechecked
  inside the share transaction. The same rule lets the receiver remove an
  extra filing again.
- Ordinary invitations still require filing, and the dialog says why.
- One ReceivedItemDialog body serves acceptance and later filing for
  recordings and mail. Folders created in it reach the dashboard state.
- Removing a direct share says where the item stays visible and keeps the
  row.

No schema change. Decision record:
2026-10-31-share-acceptance-with-existing-folder-access.
@claude

claude Bot commented Oct 31, 2026

Copy link
Copy Markdown

Review: fix(sharing): show folder access when sharing an item and accept it without extra filing

Implements R1a-R4a from documentation/adr/2026-10-31-share-acceptance-with-existing-folder-access.md: the share dialog now discloses folder audiences and skips redundant direct invites to them (R1), receivers can accept a direct invitation without filing when an accepted folder path already exists, rechecked inside the share transaction (R2), ordinary invitations still require filing (R3), and an extra filing can be removed again while the direct share stays (R4). Verified the new item-folder-audience.ts raw SQL (placeholder bound, scoped to the caller, excludes self and inactive/org recipients), changePersonShare's recheck logic, and the broadened dashboard receivedFolderIds computation. Traced the Codex-reported onFolderCreated fix through all four call sites (workstation.tsx, workstation-detail-pane.tsx, mail-detail-pane.tsx) - correctly wired. Test suite is thorough: the 19-case integration suite covers legacy direct/folder overlaps, pending/removed/unfiled path revalidation, IdP inactive recipients and cross-user isolation, and the UI suites cover one-click acceptance, folder grouping, and unfiling. No schema, env or deploy-surface changes; ADR front matter, cross-links and index are consistent.

Verdict: APPROVE

Findings: Blocker 0 | Critical 0 | Major 0 | Minor 0 | Nit 0

Findings

None. No security, correctness, scoping or encryption issues found; raw SQL in src/db/queries/item-folder-audience.ts and the extended src/db/queries/item-shares.ts queries follow the parameter-binding and allowlist rules, and every query is scoped to the caller (requireOwner, receiverUserId checks).

Missing tests

None identified. The adaptation of folder-shares.integration.test.ts to the new invite-skip ordering (and the explicit raw-insert for the "legacy overlap" case) shows the existing suite was already re-validated against the behavior change.

@novoj
novoj merged commit 4635594 into dev Oct 31, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant