Conversation
copy_move only knew the binary isPublic flag, so an unlisted parent was treated as private. Copying into an unlisted folder produced a private child, and moving content there left it private -- both violating the rule updateVisibility enforces, that a child may not be less public than its parent. The practical symptom: someone holding an unlisted folder's link sees its other children but not the newly copied one. Read the parent's visibility instead. A copy inherits it directly; moved content is raised to it via a new raiseVisibility helper, which promotes only content below the target level so that moving a folder holding public content into an unlisted one does not hide that content. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K3bUTUym3xhuXLegDyTNZ2
The visibility and share-timestamp updates share one filter that already selects exactly the rows whose visibility changes, so a single updateMany does the job and removes the statement-ordering subtlety. Also document what raiseVisibility does not check. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K3bUTUym3xhuXLegDyTNZ2
Read the moved content's `visibility` rather than the legacy `isPublic` flag, and apply the library draft guard to unlisted parents as well as public ones: moving into any shared parent raises the draft's visibility, which shares curated content implicitly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K3bUTUym3xhuXLegDyTNZ2
An unlisted parent cannot occur for library content: `moveContent` requires
the parent to share the content's owner, and the library account's content is
only ever set public (on publish) or private (on unpublish or creation).
Guarding unlisted parents therefore adds an unreachable, untestable branch and
an error message ("published folder/activity") that would not describe it.
Keep reading `visibility` rather than the legacy `isPublic` flag.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3bUTUym3xhuXLegDyTNZ2
Contributor
|
@dqnykamp Looks like there are some merge conflicts now. How does this preserve the "public checks" invariant? If I move an inaccessible doc into a public folder, what happens? I think what should happen is that: you get a message saying you can't move non-public content into a public folder. That's the easiest thing for us to do that preserves the invariant. If that approach ends up being too annoying, we could find other ways later. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Independent of #3023 (both branch from
main); the two can land in either order.Problem
updateVisibilityenforces that a child may not be less public than its parent (access/visibility.ts:76-85).copy_move.tspredatesunlistedand still reasons in terms of the binaryisPublicflag, so it treats an unlisted parent as private and breaks that invariant:copy_move.ts:656-657):visibility: desiredParentIsPublic ? "public" : "private"— copying into an unlisted folder produced a private child.copy_move.ts:329-335): only promoted whenparent.isPublic, so moving content into an unlisted folder left it private.Practical symptom: someone holding an unlisted folder's link sees its other children but not the newly copied or moved one.
This also undermines the reachability argument that #3023 relies on, which assumes the invariant holds in the data.
Fix
Read the parent's actual
visibilityinstead ofisPublic:raiseVisibilityhelper.Why a new helper rather than
updateVisibilityupdateVisibilitycascades one visibility to every descendant, so it can demote. Using it here would mean that moving a folder containing a public doc into an unlisted folder silently hides that doc.raiseVisibilitypromotes only content strictly below the target level, leaving anything already more public untouched. It replaces the previoussetContentIsPubliccall on the move path; for a public parent the outcome is identical, since nothing can be more public than public.The library guard ("Cannot move draft from library to published folder/activity") keeps its existing scope: it fires only for a public parent. Moving a draft into an unlisted folder is not publishing it. Its content check now reads
visibilityrather than the legacyisPublicflag, which is equivalent since the two are kept in sync.Testing
Three new tests in
copy_move.test.ts:raiseVisibilityskips assignments and does not re-check ownership or the public-sharecriteria, matching the
setContentIsPubliccall it replaces: the content is following aparent that already satisfies them.
Full API suite passes: 383 tests across 27 files.
Not addressed here
Existing rows in production may already violate the invariant, since this bug has been live. A data audit is worth doing separately. The deprecated
setContentIsPublic(query/share.ts:20) is another binary-visibility path still in use.🤖 Generated with Claude Code
https://claude.ai/code/session_01K3bUTUym3xhuXLegDyTNZ2