- Tighten Document.findByIds so isPrivate filtering fails closed when
the attribute is not loaded, and include isPrivate in the projection
used by Relationship.findSourceDocumentIdsForUser so backlinks from
restricted docs are no longer leaked to collection-only members.
- Add !isPrivate gate to the unpublish policy so collection writers
without direct membership cannot unpublish restricted documents.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Auto-subscribe mentioned users to documnet
* Add tests for mention auto-subscribe and a buildMention factory
* Add tests that prior unsubscribes are respected when mentioned
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Batch mention subscriptions into a single transaction
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* wip
* Remove obsolete snapshots
* simplify
* chore(test): Convert mocks to TypeScript and tighten fetch mock types
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Remove unneccessary patches
* Migrate to msw instead of custom fetch mock
* Address PR review comments
- Split chained vi.useFakeTimers().setSystemTime() into separate calls.
- Switch test setup to dynamic imports so EventEmitter.defaultMaxListeners
assignment runs before module init (static imports were hoisted above it).
- Drop redundant NODE_ENV guard in monkeyPatchSequelizeErrorsForJest; its
sole caller already gates on env.isTest.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: Replace lodash with es-toolkit
Migrate all direct lodash imports to es-toolkit/compat for a smaller,
faster, lodash-compatible utility library. Transitive lodash usage from
other packages remains unchanged.
* fix: Restore isPlainObject semantics in CanCan policy
The lodash migration aliased `isObject` to `lodash/isPlainObject` and
the codemod incorrectly mapped the local name to es-toolkit's `isObject`,
which also returns true for arrays and functions. This caused condition
objects in policy definitions to be skipped, breaking authorization
checks across the codebase.
* fix: Restore unicode-aware length counting in validators
es-toolkit/compat's size() returns string.length, while lodash's _.size()
counts unicode code points. Switch to [...value].length to preserve the
previous behavior so multi-byte characters like emoji count as one.
- Use transient `$rtl` prop on Meta styled component so it isn't forwarded to the DOM
- Wrap ActionButton in observer so action visibility checks read MobX computed values inside a reactive context
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: Vendor request-filtering-agent
* fix: honor fetch timeout and undefined allow list in proxy pre-flight
Default allowIPAddressList to [] so an unset ALLOWED_PRIVATE_IP_ADDRESSES
env var doesn't overwrite the agent's default and crash on .length, and
race the pre-flight DNS lookup against the request's abort signal so the
configured fetch timeout applies to slow DNS resolution.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Plumbed `dictionary` props through editor components, menus, extensions,
and nodes. Replaces with `useTranslation()` in React contexts and direct
`t` imports from i18next elsewhere.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* Allow viewers to create and access API keys
Still guarded by their view permissions
* Drop Member role gate from apiKeys routes
Lets viewers reach the createApiKey/listApiKeys/delete policy checks now
that the policy itself permits them. Updates CleanupDemotedUserTask to
retain viewer keys and adds coverage for viewer create + guest reject.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Tighten apiKeys test assertions and broaden viewer coverage
- Use not.toBeNull() instead of toBeTruthy() for retention check
- Add viewer coverage for apiKeys.list and apiKeys.delete
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix: Open notifications in a bottom drawer on mobile
Match the mobile context menu pattern by rendering the notifications
panel as a Vaul bottom drawer below the tablet breakpoint, while
keeping the existing Radix popover on desktop.
* fix: Notification drawer opens at correct height on mobile
Skip the height animation while bounds is unmeasured to avoid a
feedback loop between framer-motion's animation toward 0 and the
ResizeObserver re-targeting it. Eagerly import Notifications so first
paint has real content for the initial measurement, and bump its
minHeight to 75vh on mobile to match other bottom drawers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Increase emoji picker cell size on mobile
Mobile uses a 40px button with a 32px emoji glyph (vs. 32px / 24px on
desktop), so roughly 8 emojis fit across a typical phone screen for
easier touch targeting.
https://claude.ai/code/session_017Rrv75Rc6eZ7eb2iNpZxpu
* tweaks
---------
Co-authored-by: Claude <noreply@anthropic.com>
@emotion/stylis compiles top-level `::highlight(name)` rules inside a
styled component as a compound selector `.parent::highlight(name)`,
which only matches highlights on the editor container element itself.
Chrome applies these leniently, but Firefox correctly requires the
originating element to contain the highlighted text. Prefixing with
`&` forces a descendant combinator so descendant elements containing
the highlighted text are matched.
Closes#12270
* chore(test): drop no-op per-test Redis flushall
The afterEach created a fresh ioredis-mock client and flushed it, which
doesn't clear state held by clients elsewhere in the test. Removing the
hook saves a few ms across thousands of test cases.
* Cache Jest transform cache
Drop the dedicated setup job that blocked every other job for ~60s,
extract the install steps into a reusable composite action, drop the
unnecessary bundle-size dependency on types, and switch test-server
sharding to Jest's native --shard flag.
* fix: relative path returned from MCP
* fix: MCP create_attachment uploadUrl and size validation
Make uploadUrl absolute against team.url so MCP clients can resolve it
without a base, tighten the size schema to match the REST endpoint
(int, nonnegative, finite), and stub cookies on the MCP API context so
LocalStorage's CSRF-aware getPresignedPost works for Bearer-authed
MCP requests. Adds tests covering the success path, persistence, size
limits, schema rejections, and read-only scope enforcement.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: Update editor generics
* fix: Address PR review on editor generics
- Restore null-guard on Link click handler so anchors aren't inert when no onClickLink is provided
- Mark onClickLink optional in LinkOptions and openLink command to match runtime
- Remove dead `collapsed` option from HeadingOptions
- Make ToggleBlock dictionary optional and restore optional-chained access for server-side schema instantiation
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: Add delete_document and delete_collection MCP tools
Adds MCP tools for deleting (or archiving) documents and collections.
Refactors Document#delete into destroyWithCtx and extracts collection
archive logic into Collection#archiveWithCtx so the same code paths can
be shared between the REST API and MCP entry points.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: Wrap MCP delete tools in DB transaction
Ensures delete/archive of documents and collections via MCP is atomic
and that row locks (transaction.LOCK.UPDATE) inside *WithCtx methods
actually apply, matching the pattern used by move_document.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* docs: Clarify delete_collection MCP tool description
Reflects that collection deletion only soft-deletes non-archived
documents via the BeforeDestroy hook.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: promote no-explicit-any from warn to error and resolve violations
Upgrades the oxlint rule severity and removes all 40 existing
`no-explicit-any` warnings across the codebase. Most call sites gained
proper types (SharedEditor refs, JSONNode/JSONMark for ProseMirror JSON
walking, DocumentsStore, dd-trace `Span` parameter inference, prosemirror
Fragment public API in place of internal `(fragment as any).content`).
A few load-bearing `any` uses were preserved with scoped disable
comments where changing the type would cascade widely (Sequelize JSONB
columns on `Event`, the `withTracing` higher-order function generic,
`Extension.options` consumed by many subclasses, dd-trace's `req`
patching).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces `as any` casts when constructing OAuth2Server Request/Response
with explicit objects containing the fields the library actually
consumes, and switches BaseStorage's manual header spread to a
node-fetch `Headers` instance to avoid the no-misused-spread warning.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: Add breadcrumb to MCP responses
* test: Update MCP test expectations for new response envelope
Tests were reading the old flat document shape; update them to read
through the new { document, breadcrumb } envelope.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* perf: Batch collection lookups when building breadcrumbs
Add getBreadcrumbsForDocuments helper that loads all referenced
collections in one query (with the user's memberships) and resolves
breadcrumbs from the per-collection cached documentStructure. Use it
in list_documents and move_document, replacing the per-document
Collection.findByPk that produced an N+1 query pattern.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* test: Add coverage for getBreadcrumbsForDocuments and parallelize doc + breadcrumb loads
Run presentDocument and getDocumentBreadcrumb concurrently in fetch,
create_document, and update_document so the breadcrumb lookup no
longer adds latency on top of the presenter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* chore: resolve no-explicit-any lint warnings in plugins
Replaces uses of `any` in the plugins directory with concrete types,
`unknown`, or structured type assertions, addressing the remaining
typescript-eslint(no-explicit-any) warnings flagged by oxlint.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* chore: address review feedback in GitLabIssueProvider
Drop trailing semicolon from log string and add early return in
`destroyNamespace` when neither `user_id` nor `full_path` is present
to avoid an unnecessary full-scan transaction.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>