Commit Graph
99 Commits
Author SHA1 Message Date
sandrodachandClaude Opus 5.5 bc7bdc481e chore(release): v0.10.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m16s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:47:15 +01:00
sandrodachandClaude Opus 5.5 7a90e6dae3 Merge branch 'feat/outliner-polish' into dev
Offer /number at start or end like the other block commands and start a
numbered list when typing "1. " into an empty bullet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:44:20 +01:00
sandrodachandClaude Opus 5.5 2bfe74e66b feat(workspace): numbered lists and reliable markdown paste
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m5s
- block type 'numbered' (/number): 1., a., i. by nesting, continues on
  Enter, an empty item ends the list; markdown export/import as 1.
- pasting: parser moved to lib/pasteOutline with tests; blank lines split
  paragraphs, numbered lists keep their type, indentation levels follow
  the widths in use (2, 3 or 4 spaces, tabs)
- text that stays in the focused block after pasting (a paragraph with
  line breaks) was dropped; the block now takes it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:36:15 +01:00
sandrodach 1753208cba feat(ui): update instant capture, count badges, mobile triage and folder modal 2026-10-30 19:27:15 +01:00
sandrodach fd72500d17 feat(workspace): polish outliner slash commands, typography and actions overlay 2026-10-30 19:26:52 +01:00
sandrodachandClaude Opus 5.5 9008d7c915 feat(workspace): journal with one note per day and a calendar
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m6s
- journal_days (migration 8) maps a person's day to an ordinary note;
  GET /journal lists the days, POST /journal/{date} opens or creates one
- the journal sits on top of the notes sidebar: days below each other
  (today first, older ones load while scrolling), a calendar with month
  and year picker follows the day in view and jumps to any day
- the header shares the day in view; journal notes stay out of the folder
  tree; can be switched off per device under Darstellung

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:20:58 +01:00
sandrodachandClaude Opus 5.5 261579f0f2 feat(notify): own webhook as a full notification channel
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m59s
The custom webhook could be entered but never switched on since the
notification matrix replaced the old alarm channels. It is now a third
column next to e-mail and Discord for every event and the daily summary;
bundles go out as JSON (event "digest").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:02:46 +01:00
sandrodachandClaude Opus 5.5 6c154af251 fix(workspace): single scroll area, drag cleanup, thin note titles with bundled Inter
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m18s
- the workspace fills the window; only the note scrolls (also on phones, where the
  sideways scroll area used to scroll on its own)
- clear drag state on dragend, calmer sidebar toggle when collapsed
- ship Inter as variable font, light and larger note titles; header shows the
  title only after the big title scrolled away and stays one row on phones
- main builds show the package version without -dev

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:58:55 +01:00
sandrodachandClaude Opus 5.5 ad4829796c fix(settings): let the profile section use the full width
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m9s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:36:50 +01:00
sandrodachandClaude Opus 5.5 2542e0e7b8 fix(themes): white editor and grey sidebar in light theme
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m1s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:03:46 +01:00
sandrodachandClaude Opus 5.5 1b0c8ba18f chore(release): v0.9.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m9s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:51:32 +01:00
sandrodach a317ce0fee feat(workspace): add formatting shortcuts for bold, italic, and links in outliner 2026-10-30 16:22:55 +01:00
sandrodach 1d6863824b feat(workspace): add line numbers and horizontal scrolling to code block editor 2026-10-30 16:17:17 +01:00
sandrodach 108ac6621c fix(themes): improve contrast for code blocks and callouts in light theme 2026-10-30 16:12:36 +01:00
sandrodach e8c7c55dd5 docs(changelog): note group-shared task lists in daily summary for 0.8.0 2026-10-30 13:38:21 +01:00
sandrodachandClaude Opus 5.5 6100d339f1 chore(release): v0.8.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m16s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:00:09 +01:00
sandrodach 4f5da9507f Merge branch 'feat/gemini-workspace' into dev
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	CHANGELOG.md
2026-10-30 09:54:30 +01:00
sandrodachandClaude Opus 5.5 a69bcbaf10 feat(notify): bundled notifications, task watchers, daily summary
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m4s
- Per-user routing (own mail / own Discord webhook) for task alarms
  (sent at once), shares, completed shared tasks and watched tasks;
  settings as JSON on the user (GET /auth/me, PATCH /auth/settings).
- Everything but alarms is queued and sent as one message per user
  after NOTIFY_DIGEST_MINUTES (default 5); mails now multipart with an
  HTML version, Discord as one embed. Three failed attempts drop it.
- Own changes never notify the actor, except on watched tasks when
  asked for; "paused" stops everything including alarms.
- Task watchers: POST/DELETE /tasks/{id}/watch, isWatching on tasks.
- Daily summary at a chosen time: overdue, today, tomorrow, plus the
  count of the next 7 days; nothing due, nothing sent.
- Migration 7; jobs do not run in the demo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:49:13 +01:00
sandrodach 5f27e7ca9c feat(workspace): move status pills to tab bar and add undo/redo and actions menu to note header 2026-10-30 09:41:02 +01:00
sandrodach fc7b2b3a2c Merge remote-tracking branch 'origin/dev' into feat/gemini-workspace
# Conflicts:
#	CHANGELOG.md
2026-10-30 09:33:23 +01:00
sandrodach d2afcf49df feat(notifications): add channel routing matrix, daily summary, and task watch button 2026-10-30 09:32:52 +01:00
sandrodach 6795edbf4b feat(voice): live dictation with browser pause restart and server audio chunking 2026-10-30 09:27:30 +01:00
sandrodach 446f8e4649 fix(workspace): tighten link preview card, slash menu matching/scrolling, and Enter on last empty bullet 2026-10-30 09:21:29 +01:00
sandrodachandClaude Opus 5.5 362dd3b4c6 fix(workspace): extract replaces the branch in the editor, with undo
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m2s
The server only creates the new note and returns the link; the editor
swaps the branch for it as an ordinary own edit through the sync engine.
No more clash with unsent typing (conflict copies), the link shows at
once also with polling, and Strg+Z restores the branch. Undoing (toast or
Strg+Z) puts the new note into the trash via POST /extract/undo. The
sidebar gets the new note right away and opens its folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:18:25 +01:00
sandrodachandClaude Opus 5.5 02ce554c02 chore(release): v0.7.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 9s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 00:26:26 +01:00
sandrodachandClaude Opus 5.5 4d1b37c956 feat(workspace): turn a branch into its own note, merge notes
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m56s
- Extract: button on the bullet (desktop) or /extract (/notiz). The bullet
  becomes the title (hashtags stay at the link), its children the content
  of a new note in the same folder with the source's shares (a foreign
  source owner gets write access); the branch becomes [[title]] through
  the operation log, so open editors follow.
- Merge: drop a note onto another in the sidebar or use "Mit anderer
  Notiz zusammenführen…" in the note header. The own source is appended
  as an h2 section with its bullets below and goes to the trash; the toast
  offers a complete undo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 00:25:46 +01:00
sandrodachandClaude Opus 5.5 4c26eb2960 feat(workspace): link previews above bullets with a web address (M5)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- GET /link-preview?url= fetches the page on the server (https only,
  SSRF-guarded like webhooks), reads Open Graph/Twitter tags, title,
  description and icon from the head, loads picture and icon (no SVG) and
  keeps them in link_previews (migration 6) for 7 days; readers' browsers
  never contact the page. Off in the demo; 300 fetches per address in
  15 minutes.
- Compact card above the bullet (icon, site, title, one line, small
  picture); the duplicate link badge is left out.
- ✕ turns the address into [title](url), so hiding syncs with the note;
  "Link-Vorschauen anzeigen" under appearance switches all off per device.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 00:06:05 +01:00
sandrodachandClaude Opus 5.5 83408d120d fix(workspace): more room for notes on phones
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m57s
Almost no side margin, 14 px indent per level (22 px from tablet width
on), zoom and delete buttons only take width in the active row. Very deep
rows keep about 14rem and the note scrolls sideways instead of squeezing
the text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:55:00 +01:00
sandrodachandClaude Opus 5.5 56c1fa02e6 feat(mail): sender display name (SMTP_FROM_NAME, default MindSift)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m54s
A bare SMTP_FROM address gets the display name in the From header; a name
already in SMTP_FROM wins, the envelope keeps the bare address. Also a
field in the admin mail settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:47:38 +01:00
sandrodachandClaude Opus 5.5 1f63e08a73 feat(media): images and recordings in backups, exports and imports (M6)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- Backup ZIP (download and automatic per-user server backups) carries the
  files of the user's own notes as media/<id><ext>; restoring creates
  them with new IDs and rewrites the blocks.
- Markdown archive puts them under attachments/ and embeds them relative
  to each note (![caption](../attachments/…)); re-importing turns them
  back into image/audio blocks.
- Obsidian import takes images and audio a note embeds on its own
  (![[file.png]], ![](path/file.png)); unused or invalid files appear as
  skipped in the preview instead of vanishing.
- Format detection and file paths moved into storage for this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:41:26 +01:00
sandrodachandClaude Opus 5.5 3f2bc96732 feat(workspace): dictation via /diktat (M4)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m59s
/diktat (only in an empty bullet, only with voice input available)
listens right away; the bullet becomes one button with the live wave
across it and a translucent "Stopp" on top. A tap ends it and the
recognised text lands in the bullet as plain text. Uses the configured
speech recognition (own Whisper server or the browser); Esc cancels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:30:15 +01:00
sandrodachandClaude Opus 5.5 3f5e3b2ac1 feat(workspace): voice notes via /audio (M3)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m10s
- /audio (only in an empty bullet) shows a recording bubble: green round
  button starts, it turns red with a live wave and timer on its left, a
  tap saves the recording as an inline audio player. An audio file can be
  uploaded instead; Esc/✕ restores the empty bullet.
- Chrome's WebM recordings get their length measured, so the player shows
  the total time and seeking works.
- With the own Whisper server "Transkribieren" turns the recording into
  the (searchable) caption.
- Loaded files keep their Blob, as the CSP rightly blocks fetch() on blob:
  URLs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:23:54 +01:00
sandrodachandClaude Opus 5.5 e8fa14a4cb feat(workspace): image blocks via /bild (M2)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m18s
- /bild (only in an empty bullet) turns the bullet into an inline picker:
  file, camera on phones, drag & drop, paste, or an https link the server
  copies. Esc/✕ restores the empty bullet; nothing is synced before the
  upload succeeded.
- Photos are shrunk to 2048 px and stored as WebP (JPEG fallback); the
  re-encoding drops EXIF data such as the location.
- Image block: loaded with the login as blob URL, click opens full
  screen, optional caption kept in the block content
  (![caption](media:id)).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 23:14:08 +01:00
sandrodachandClaude Opus 5.5 177fa49363 feat(media): storage for images and audio in notes (M1)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m4s
- Table media (migration 5), files in $DATA_DIR/media/<docId>/.
- POST /documents/{id}/media (write access), POST .../media/fetch copies an
  external https image (SSRF-guarded, not in the demo), GET /media/{id}
  with range requests for readers of a note that shows the file.
- Format detected from the content (no SVG); own sandbox CSP on answers.
- Blocks point to files through their content (media:<id>), so the note
  sync needs no change; compaction removes files no block mentions any
  more after a day. Demo reset and demo start clear the folder.
- Limits MEDIA_MAX_IMAGE_MB, MEDIA_MAX_AUDIO_MB, MEDIA_QUOTA_MB,
  MEDIA_DEMO_MAX_MB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:57:59 +01:00
sandrodachandClaude Opus 5.5 e385a44fb9 chore(docker): explanations in .env.example, whisper as commented block
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
- docker-compose.yml only maps variables; every variable is explained in
  .env.example (German, with defaults, units and choices).
- The whisper service is a commented block to switch on instead of a
  compose profile.
- TZ, TRUSTED_PROXIES, LOGIN_PROTECTION, DEMO_RESET_MINUTES and
  LEGAL_*_CONTENT are now passed through (they had no effect from .env).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:51:57 +01:00
sandrodachandClaude Opus 5.5 d396d42acf docs(changelog): hold-to-record cancels by dragging up
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 7s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:49:32 +01:00
sandrodachandClaude Opus 5.5 d52992afd2 Merge branch 'changelog_backlog' into dev
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:49:02 +01:00
sandrodachandClaude Opus 5.5 cc68d3f334 fix(workspace): keep the cursor in a block that turns into a code block
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m58s
Converting via /code or ``` swapped the text field for the code editor's
and left the focus nowhere, so further typing triggered app shortcuts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:48:35 +01:00
sandrodach b624093980 docs(changelog): backfill release history from v0.1 to v0.5.2 2026-10-29 22:42:43 +01:00
sandrodachandClaude Opus 5.5 7fa21e485b feat(voice): all microphone buttons use the server's speech recognition
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m56s
- New useVoiceInput hook (lib/voice.ts): "server" records with MediaRecorder
  and sends to /voice/transcribe, "browser" keeps the live recognition,
  "off" or missing browser support hides the microphone.
- Quick dump bar, mobile capture sheet and hold-to-record use it; live
  waves from the real input level (VoiceWave) and "Wird erkannt…".
- Recordings stop after STT_MAX_SECONDS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:23:48 +01:00
sandrodachandClaude Opus 5.5 7801cd13b9 feat(voice): self-hosted speech recognition via Whisper (STT_*)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m49s
- STT_URL switches voice input to an OpenAI-compatible Whisper server
  (e.g. speaches); without it the browser's recognition stays. Configured
  by environment only, with limits for upload size, parallel jobs, hourly
  budget per user and timeout. The demo always uses the browser.
- POST /voice/transcribe forwards recordings and returns the text; nothing
  is stored. On startup MindSift waits for the server and asks it to
  download the model if missing.
- Admin card shows the active mode and server state, with a test recording.
- docker-compose: optional "whisper" service (speaches 0.8.3 CPU, profile
  "whisper", models in ./whisper).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:12:57 +01:00
sandrodachandClaude Opus 5.5 6a5e82431f chore(release): v0.6.1
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m6s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:20:00 +01:00
sandrodachandClaude Opus 5.5 fbc404fea1 fix(notes): no self-conflicts when typing in a rhythm
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m51s
Several unsent text changes of one block were applied one by one to the
local view, numbering local versions ahead of the server, which folds them
into one change (formBatch). The focused field kept the inflated version as
base, so the next edit after a sync conflicted with the user's own text.
The local view now applies pending ops as they will be sent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:13:02 +01:00
sandrodachandClaude Opus 5.5 b55334b163 chore(release): v0.6.0
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m8s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 20:40:59 +01:00
sandrodachandClaude Opus 5.5 9d9698186c fix(security): demo sends nothing, hidden SMTP password, body limits (FLAW-33..38)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- Demo: senders for mail, Discord and webhooks refuse, no alarm ticker;
  test alarm, SMTP test, server settings, backups, account and session
  changes of the shared demo accounts answer 403; the session list only
  shows the own device. The UI shows the notices and disables the controls.
- SMTP password is never sent back (smtpPassSet), empty keeps it.
- ?token= on webhook ingest accepts only API keys.
- Request bodies capped at 2 MB (sync 8 MB, imports 101 MB).
- Deleting an account removes its server backups.
- Backup downloads, exports and import uploads get 30 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:43:23 +01:00
sandrodachandClaude Opus 5.5 3709282a4f fix(auth): longer IDs and invite codes, register limits, single-use invites (FLAW-32, FLAW-39, FLAW-40)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m2s
- NewID uses 96 random bits; invite codes get their own 100 bits in Base32.
- Registration and forgot-password are limited per address via loginGuard.
- The invite is claimed atomically before the account is created and
  released again when the account cannot be created.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:28:09 +01:00
sandrodachandClaude Opus 5.5 1af3a6e90a feat(auth): server-side sessions and current password for account changes (FLAW-30, FLAW-31)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- Every login is a session (device, IP, last use); the token's jti is its ID.
  Sessions end on logout, per device from the profile, or after 30 idle days.
- Tokens older than a day are renewed via the X-Session-Token header.
- Changing password or login e-mail needs the current password; a new
  password logs out all other devices and mails the old address.
- Demo reset keeps the demo visitors' sessions.
- revoked_tokens is replaced by sessions (migration 4); everyone is logged
  out once after the upgrade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:25:22 +01:00
sandrodachandClaude Opus 5.5 b2ecda9896 fix(security): safe links and security headers (FLAW-28, FLAW-29)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m48s
safeHref lets only http, https and mailto become links (Markdown viewer,
outliner, legal links); javascript: and friends show as text. A
middleware sets a Content-Security-Policy (scripts only from MindSift,
no framing, connections only to this server), X-Frame-Options,
nosniff, Referrer-Policy and a Permissions-Policy. The two inline
scripts of index.html moved to files so script-src stays 'self'.

The second inline script also deleted every cache on each page load,
which undermined the offline start; it is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:02:13 +01:00
sandrodachandClaude Opus 5.5 3ca4ff7bce chore: Semantic Versioning and a changelog from now on
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m50s
Tags become three-part (v0.6.0), the header shows the full version and
pre-release tags no longer move :stable. CHANGELOG.md (Keep a Changelog)
starts with an Unreleased section; older versions will be added from the
history. The quantity field opens the number keypad on phones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 18:55:32 +01:00