Mark comments (and, via existing page provenance, pages) created under an
is_agent service account as authored by AI, derived from the SIGNED server
identity rather than any client field, and render the existing AI badge in
the comments sidebar.
Backend (B1):
- Add additive users.is_agent boolean (default false) migration; reflect in
the Users Kysely type, the user repo baseFields, and (via Selectable) the
User entity.
- jwt.strategy: derive req.raw.actor from user.isAgent (an is_agent account
stamps every write 'agent'); external MCP has no internal ai_chats row so
aiChatId stays null. Non-spoofable: a plain user cannot obtain
created_source='agent'.
- Loosen the provenance aiChatId type to string|null across token.service and
the JwtPayload/JwtCollabPayload claims (type-level only; the internal AI-chat
path still passes a real aiChatId).
Frontend (B2):
- Extend IComment with createdSource/aiChatId/resolvedSource (backend already
returns them via selectAll).
- Extract the local AiAgentBadge from history-item into a shared
components/ui/ai-agent-badge.tsx (clickable deep-link when aiChatId present,
plain label when null/absent); reuse it in history-item and render it in
comment-list-item next to the author name when createdSource==='agent'.
Tests: comment.service agent/null-aiChatId provenance, jwt.strategy provenance
derivation + anti-spoof, AiAgentBadge clickable/non-clickable branches, and
comment-list-item badge render/no-render.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Widen the comments/aside panel from 350 to 420 (~20% wider)
- Remove double padding around the panel: AppShell.Aside p="md"->"sm"
and inner Box p="md"->p={0}; reduce header-to-tabs gap mb="md"->"sm"
- Reduce empty space below the add-comment input (paddingBottom 25->10),
align the avatar with the input box (marginTop 10->2) and re-anchor the
send button (bottom 30->15)
- Pull the timestamp closer to the nickname via tighter line-height
(lh 1.2 on the name, 1.1 on the "… ago" text)
The Comments panel was sparse: 12px inner/outer paddings per thread, a
16px gap between avatar and body, body text at the global 16px ProseMirror
size. On a narrow aside column this ate vertical space - few comments per
screen, lots of air.
Tighten strictly inside features/comment (the shared aside frame is left
untouched, so TOC/Details tabs keep their padding):
- Thread Paper: p='sm'->p='xs', mb='sm'->mb='xs' (12->10px).
- Reply-editor Divider: my={4}->my={2}.
- CommentListItem outer Box: pb='xs'->pb={6}; the header Group
(avatar + body) gains gap='xs' (16->10px).
- Font hierarchy: author name sm->xs (14->12px, fw=500 kept), selection
quote sm->xs; comment body via a scoped CSS override on
.commentEditor .ProseMirror: font-size sm (14px) + line-height 1.4,
margin-top 10->4. The page editor is unaffected (the override is
scoped to the comment editor module).
- Selection quote padding 8->6, margin-top 4->2.
- Dropped the unused .wrapper rule (no references).
Add comment resolve/re-open as a community feature, written from scratch on top
of the infrastructure already present in the community codebase: the
resolved_at/resolved_by_id columns, the COMMENT_RESOLVED notification job, the
resolveCommentMark collaboration handler, the commentResolved websocket event,
the comment service/types and the Open/Resolved tabs. No Enterprise-Edition code
is reused and there is no EE feature gating — resolving is available to anyone
who can comment.
Backend:
- add POST /comments/resolve (ResolveCommentDto) guarded by validateCanComment;
reject resolving replies
- add CommentService.resolveComment: set/clear resolvedAt/resolvedById, sync the
inline comment mark via collaboration handleYjsEvent, queue
COMMENT_RESOLVED_NOTIFICATION (only when another user resolves), emit the
commentResolved websocket event and write a resolve/reopen audit log
Frontend:
- add useResolveCommentMutation with optimistic update + rollback
- add ResolveComment toggle button
- wire the resolve button and menu item into comment-list-item / comment-menu,
gated on canComment for parent comments
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Strip the proprietary client EE so the fork ships a clean community/AGPL
edition, mirroring Forkmost. Delete apps/client/src/ee (201 files) and
packages/ee, and patch every consumer that imported from @/ee/*.
- gate-out EE features (useHasFeature -> false): API keys, SSO, MFA, SCIM,
audit logs, AI / AI-chat, templates, page permissions, page verification,
comment resolution, trash retention, viewer comments
- drop cloud/billing/trial/entitlement/posthog flows; sign-in is now
email+password only (no SSO/LDAP/cloud)
- remove EE routes from App.tsx and EE entries from sidebars/settings nav
- restore the community page-share button (ShareModal) that the EE
PageShareModal used to provide
- remove the dead "Attachments" search filter, dead MFA navigation and
orphaned route constants
Client type-checks clean; full `pnpm build` is green for all three projects.
* fix: cursor jumps to end of text when editing a comment
When editing a comment mid-text, the cursor would jump to the end after
every keystroke, making it impossible to insert text at any position
other than the end.
Root cause: on each keystroke, the comment editor's onUpdate callback
updated parent state (setContent), which changed the defaultContent prop
passed back to CommentEditor. A useEffect watching defaultContent then
called commentEditor.commands.setContent(), which reset the entire
editor content and moved the cursor to the end.
Fix:
- Store in-progress edits in a ref instead of state to avoid triggering
React re-renders and the prop->effect->setContent cascade
- Read from the ref when saving the comment
- Sync the ref back into state after a successful save so the read-only
view updates immediately
- Guard the setContent useEffect to only run for read-only editors, so
websocket-driven updates from other browsers still work
Fixes#1791
Functionally tested on Firefox and Chrome: mid-text editing, saving,
cross-browser live updates via websocket.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix stale content on edit cancel
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com>
* feat: resolve comment (EE)
* Add resolve to comment mark in editor (EE)
* comment ui permissions
* sticky comment state tabs (EE)
* cleanup
* feat: add space_id to comments and allow space admins to delete any comment
- Add space_id column to comments table with data migration from pages
- Add last_edited_by_id, resolved_by_id, and updated_at columns to comments
- Update comment deletion permissions to allow space admins to delete any comment
- Backfill space_id on old comments
* fix foreign keys
* feat: support i18n
* feat: wip support i18n
* feat: complete space translation
* feat: complete page translation
* feat: update space translation
* feat: update workspace translation
* feat: update group translation
* feat: update workspace translation
* feat: update page translation
* feat: update user translation
* chore: update pnpm-lock
* feat: add query translation
* refactor: merge to single file
* chore: remove necessary code
* feat: save language to BE
* fix: only load current language
* feat: save language to locale column
* fix: cleanups
* add language menu to preferences page
* new translations
* translate editor
* Translate editor placeholders
* translate space selection component
---------
Co-authored-by: Philip Okugbe <phil@docmost.com>
Co-authored-by: Philip Okugbe <16838612+Philipinho@users.noreply.github.com>