Move Profile page to /settings/profile and add a 302 redirect from
/settings to /settings/preferences so the first settings tab is
Preferences, not Profile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Track mousedown origin so click-outside-to-close only fires when both
mousedown and mouseup occur on the overlay backdrop, not when dragging a
text selection from inside the editor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Make db a required first parameter on all service functions (notes-service,
api-utils, tags, collaborators, attachments, rate-limit, sync/server).
This enables unit testing with in-memory databases via createTestDb().
Also removes the NODE_ENV=test bypass from rate-limit and adds optional
now parameter for time control in tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bearer token authentication now works on all /api/* routes, not just
/api/mcp. If a Bearer token is present it's validated first; otherwise
session cookie auth is used as fallback. Updates settings UI to reflect
the broader scope (tab renamed to "API", REST API curl example added)
and updates the landing page feature card.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register TaskList and TaskItem TipTap extensions, add "Task list" option
to the List dropdown in the formatting toolbar, and consolidate task list
CSS between the editor and markdown-it preview into shared styles in
app.css.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All isActive() and getAttributes() calls in the template were not
reading the tick prop, so Svelte 5 never re-evaluated them when the
editor state changed. Extracted isActive() and getAttrs() helpers
that consume tick to establish the reactive dependency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use flex-wrap instead of overflow-x-auto for the formatting toolbar —
scrolling clips absolutely-positioned dropdown popovers (CSS forces
both axes to auto). All buttons are now always visible, wrapping to a
second line on narrow screens. Remove the More dropdown entirely since
all items are top-level. Add overflow-hidden to the editor card to
prevent horizontal overflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move undo/redo to the start of the toolbar, promote inline code,
blockquote, code block, and divider to top-level desktop buttons.
The More dropdown is now mobile-only since all items are directly
accessible on desktop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Widen editor modal on desktop (max-w-xl → md:max-w-2xl)
- Extract text alignment from More into its own dropdown with contextual
icon reflecting the active alignment
- Promote undo/redo to top-level buttons on desktop (hidden on mobile,
still available in More dropdown)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace single "Insert table" button with a Table dropdown that shows
contextual row/column operations when the cursor is inside a table:
add row, add column, delete row, delete column, delete table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Install @tiptap/extension-table packages, register Table/TableRow/
TableHeader/TableCell extensions, add Table button to the More dropdown
(inserts a 3×3 grid), and style tables to match the parchment theme.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The popover is inside a top-right positioned indicator, so anchoring
to right-0 keeps it on screen on mobile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents default newline and focuses the content area (textarea or
TipTap editor) when pressing Enter in the title input.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tags are still visible as hashtags in the note content and usable
via the tag filter bar. Reduces card clutter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The default 80ms delay was too short, causing drag to activate
during normal scrolling on mobile.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add outline-none to both the NoteCard article and the NoteGrid
wrapper div to prevent browser focus outlines when dragging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace drag handle zones with dndzone for whole-card dragging via
long-press on both desktop and mobile. Removes GripHorizontal icon
and dragHandle imports entirely.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the sort mode selector UI. Notes now sort by custom order
first (drag to reorder), falling back to most-recently-updated for
ties. Drag handles are always available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tags get full width for horizontal scrolling, sort buttons sit
below aligned to the right. Side by side on desktop.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use scrollbar-width: none and ::-webkit-scrollbar to visually hide
the scrollbar while keeping swipe-to-scroll functional.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add whitespace-nowrap to TagChip so long tags stay on a single line
within the horizontally scrollable filter bar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Call loadNotes(filter) when the filter prop changes so the store
gets populated with the correct note subset for each view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change sync indicator from div to button that calls sync() on click,
with hover feedback and updated tooltip.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a fixed FAB at bottom-right on mobile instead of the inline
button that scrolls out of view. Desktop keeps the inline button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stack MCP key form, API key items, user list rows, and delete
account confirmation vertically on small screens using
flex-col/sm:flex-row. Add truncate on user names/emails.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Position drag handle as a centered horizontal grip at the top edge
of the card, out of the way of title and content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
getChangesSince was returning the owner's pinned/archived/sortOrder
for shared notes instead of the collaborator's per-user values from
noteUserState. Also filtered trashed notes from collaborator sync.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test noteCollaborators and noteUserState tables: CRUD, unique constraints,
defaults, and independent per-user state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create ShareDialog with user search autocomplete, collaborator list, and remove
- Create CollaboratorPopover for hover/click indicator on shared notes
- Add collaborator indicator to NoteCard (always visible Users icon)
- Replace trash with Leave action for non-owner shared notes
- Add share button to NoteEditor toolbar (UserPlus → Users when shared)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor notes-service to include shared notes in list/get/search/reorder
- Route per-user fields (pinned/archived/sortOrder) to noteUserState for collaborators
- Update API routes to delegate to service layer with access control
- Update sync server to handle shared note updates bidirectionally
- Add leaveNote() to client store
- Refactor search and notes API routes to use service layer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add noteCollaborators and noteUserState tables for sharing notes between
users. Implement access control helpers (canAccessNote, requireNoteAccess,
requireNoteOwnership) and collaborators CRUD service. Create API endpoints
for managing collaborators and searching users.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Existing databases created from the original migration had password_hash
as NOT NULL. This adds an auto-migration that recreates the users table
with a nullable password_hash column, enabling OAuth-only user creation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin can now toggle "OAuth-only (no password)" when creating a user.
These users have no password hash and authProvider set to 'none', so
they can only log in via an OAuth/SSO provider.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change "type": "streamable-http" to "type": "http" to match Claude
Code's actual MCP schema. Also clarify that the config targets
.claude/settings.json specifically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Dynamic import zxcvbn (820KB) in PasswordStrengthMeter so it only
loads when user starts typing a password
- Raise chunkSizeWarningLimit to 850KB for the lazy-loaded chunk
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add svelte-ignore for intentional state_referenced_locally patterns
- Wrap clickable images in button elements for keyboard accessibility
- Add proper ARIA roles (dialog, textbox) with tabindex and focus management
- Fix lightbox Escape key handling to not close parent editor overlay
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add missing userId arg to syncNoteTags() calls in notes-service
- Add seedUser option to createTestDb() for test setup
- Add explicit type annotations to MCP server.tool() callbacks (zod v4)
- Fix ambiguous getByText selector in settings e2e test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /archive, /trash, /tag/[name] routes with proper <a> links
in the sidebar. Tags visible regardless of current filter.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Settings layout with sidebar nav (Profile, MCP Server, Users)
- Profile page: display name, email, password, sessions
- MCP page: API key CRUD, JSON config with copy button, LLM prompt
- Config auto-populates with actual API key when one is created
- Remove duplicate Settings link from sidebar
- Users page integrated into settings nav (admin only)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Shared notes-service.ts with userId-scoped queries for DRY
- McpServer with tools: list/get/create/update/trash/restore/
archive/unarchive/delete notes, search, list tags, pin,
reorder, upload image
- Streamable HTTP endpoint at POST /api/mcp
- Session management with GET/DELETE handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- API key generation with SHA-256 hashing and crumbs_ prefix
- User-scoped key validation, listing, and deletion
- Bearer token auth in hooks.server.ts for /api/mcp paths
- Populates event.locals.user from API key for downstream scoping
- 13 unit tests covering CRUD, validation, and user isolation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `api_keys` table with userId foreign key to schema
- Add `@modelcontextprotocol/sdk` and `zod` dependencies
- Add auto-create SQL and test helpers for api_keys table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add userId check to /api/notes/reorder (was completely unprotected)
- Scope syncNoteTags by userId to prevent cross-user tag pollution
- Verify attachmentId belongs to noteId in attachment operations (IDOR fix)
- Remove DEFAULT 0 from userId columns so missing userId fails loudly
- Update test helpers and test data to provide required userId
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>