Repository navigation
Releases: Busnes-app/KyNotes-server
Release list
v0.4.3.1
What's Changed
- deps: offsite v0.2.1, off unpatched go-smb2 (GO-2026-5051) by @Yoshiofthewire in #99
- osv: ignore GO-2026-5932 (x/crypto/openpgp, not imported) by @Yoshiofthewire in #100
- deps: offsite v0.2.2 (SMB endpoint validation fix) by @Yoshiofthewire in #101
- Silver criteria: repeatable build check, release verification, coding standard, assurance case by @Yoshiofthewire in #102
- ci: build with the Go version go.mod names by @Yoshiofthewire in #103
- Bind the CSRF token to its session by @Yoshiofthewire in #104
- Refuse login iteration downgrades; upgrade older accounts on sign-in by @Yoshiofthewire in #108
- Bind encrypted content to its object, page and kind (content format v2) by @Yoshiofthewire in #109
- Add OpenSSF Best Practices and Scorecard badges by @Yoshiofthewire in #110
- Let admins run a backup deposit without step-up by @Yoshiofthewire in #111
- KyNotes: shared Appearance cards and suite shell scale by @Yoshiofthewire in #112
- Sync ky-ui 0.4.1 classic theme catalog by @Yoshiofthewire in #113
- Follow another tab's theme choice in Appearance by @Yoshiofthewire in #114
- chore(deps): bump modernc.org/sqlite from 1.60.1 to 1.61.0 in the go group by @dependabot[bot] in #105
- chore(ci): bump github/codeql-action/upload-sarif from 4.38.3 to 4.39.1 in the actions group by @dependabot[bot] in #107
- chore(deps): bump the npm-build group in /web with 3 updates by @dependabot[bot] in #106
- Calm the workspace and Settings hierarchy by @Yoshiofthewire in #115
- Enforce the shared offsite SFTP policy in KyNotes by @Yoshiofthewire in #116
- Document secondary controls and isolate capture sources by @Yoshiofthewire in #117
- Refine KyNotes reading and phone page navigation by @Yoshiofthewire in #118
Full Changelog: v0.4.3...v0.4.3.1
v0.4.3
Upgrade notes
docker-compose.ymlno longer trusts every private network as a reverse proxy: the
TRUSTED_PROXY_CIDRSdefault is now empty. Set it in.envto your proxy's own address (for
exampleTRUSTED_PROXY_CIDRS=172.20.0.5/32) before upgrading. Otherwise every user shares the
proxy's login rate-limit bucket, and an SSO callback or KySignOn pairing URL derived from the
request (no redirect URI configured) uses KyNotes' own scheme and host.GET /api/v1/installer/networkshows whether the proxy is trusted.X-Forwarded-ProtoandX-Forwarded-Hostnow count only from a trusted proxy, like
X-Forwarded-For. Before, any client could choose the SSO callback host and the state cookie's
Secureflag when no redirect URI was configured.
Changes
-
Security: the image is built with Go 1.27.3 (was 1.27.2) for GO-2026-6809:
crypto/x509now
distrusts compromised intermediate certificates.go.modsetstoolchain go1.27.3so
go buildfrom source uses it too. -
The apply-setup and
--checkhandover addsblobTargetConfigured.falsemeans KyNotes
copies no note ciphertext itself, so the capsule alone is not a full backup. -
New: "Export notebook" downloads the open notebook as a zip of Markdown pages, canvas pages and
attachments. The browser decrypts and builds it; the server sees nothing new. The file is not
encrypted, and the browser asks before writing it.docs/EXPORT.mddescribes the layout. -
Tasks can carry dates in their text:
due:2026-11-01,repeat:weekly(alsodaily,monthly,
yearly,every-3-days,every-2-weeks) andremind:2026-11-01T09:00, in your browser's time.
The work queue groups open tasks into Overdue, Today, Upcoming, Later and No date, and shows each
due date and whether it repeats. Ticking a repeating checklist item adds the next one below it. Turn
on "Show reminders while KyNotes is open" in Settings to get a notification while a KyNotes tab is
open; it says only "A task is due" unless you also turn on "Show task text in reminders". Reminders
that passed with no tab open show as missed in the work queue. Dates and reminders stay inside your
encrypted pages; the server learns nothing new. -
Optional push reminders: add
push:yesbeside aremind:time and turn on "Also remind me when
KyNotes is closed" in Settings. The browser then sends the server only each reminder's time and an id
the server cannot link to a task, and at that time the server sends an empty push through your
browser's push service; the notification says only "A reminder is due". Off by default; the setting
names what the server and the push service learn. Reminder settings are now per account. The server
createssecrets/vapid.keyon first start (migration 0028 adds two tables) and needs outbound HTTPS to
the browser push services for this feature. -
New:
kynotes-mcp, a local MCP server that lets an AI agent read one notebook, and with the
editor role add pages and append text, as its own KyNotes account. It decrypts on your machine;
the server still sees only ciphertext. It cannot delete or change existing text. Removing the
agent from the team revokes it.docs/MCP.mddescribes setup. -
Fixed: after restoring your key with a recovery code (or linking this browser, or resetting
your key), notebooks and pages that could not be read before now appear without a reload. -
The recovery-code text now says when you need the code: no browser holds your key and your
password cannot open it, as after an administrator resets your password, and always on a single
sign-on account. -
Fixed: the admin console opens at its top after first-run setup instead of partway down.
What's Changed
- docs: verify release images against the release-image.yml signer by @Yoshiofthewire in #73
- chore(deps): bump node from 26.10.0-bookworm-slim to 26.12.0-bookworm-slim by @dependabot[bot] in #74
- chore(deps): bump github.com/Busnes-app/ky-primitives from 0.9.0 to 0.10.0 in the ky-primitives group by @dependabot[bot] in #75
- chore(deps): bump golang from 1.27.0 to 1.27.2 by @dependabot[bot] in #76
- chore(deps): bump golang.org/x/crypto from 0.57.0 to 0.58.0 in the go group by @dependabot[bot] in #77
- chore(deps): bump the npm-build group in /web with 2 updates by @dependabot[bot] in #78
- chore(deps): bump the npm-runtime group in /web with 5 updates by @dependabot[bot] in #79
- chore(ci): bump ossf/scorecard-action from 2.4.4 to 2.5.0 in the actions group by @dependabot[bot] in #80
- test(health): pin the ky.health/1 wire contract by @Yoshiofthewire in #81
- feat(web): export a notebook as a zip of Markdown and attachments by @Yoshiofthewire in #82
- feat(web): task due dates, recurrence and in-tab reminders by @Yoshiofthewire in #83
- feat: Go port of note payload crypto for the MCP bridge by @Yoshiofthewire in #85
- feat: opt-in push reminders when KyNotes is closed by @Yoshiofthewire in #84
- feat(mcp): kynotes-mcp, a local MCP bridge to one notebook by @Yoshiofthewire in #86
- Polish KyNotes interface while preserving controls and settings by @Yoshiofthewire in #88
- fix: trust no proxy by default; trust forwarded headers only from it; flag capsule-only backups by @Yoshiofthewire in #87
- docs: clarify standalone installation and test coverage by @Yoshiofthewire in #89
- Remove obsolete pre-launch owner-move upgrade note by @Yoshiofthewire in #90
- Stop pre-filling a personal KyRecovery URL in admin backups by @Yoshiofthewire in #91
- Fix three web bugs found while filming the launch videos by @Yoshiofthewire in #92
- Bump Node to 26.12.1 (CVE-2026-111497) by @Yoshiofthewire in #93
- Release Dependabot changes daily as vX.Y.Z.N by @Yoshiofthewire in #94
- build: Go 1.27.3 for GO-2026-6809 by @Yoshiofthewire in #95
- release: v0.4.3 by @Yoshiofthewire in #96
- Send comment mentions and accept only notebook members by @Yoshiofthewire in #97
- Open the emoji menu only at a word start with two letters by @Yoshiofthewire in #98
Full Changelog: v0.4.2...v0.4.3
v0.4.2
Upgrading from 0.4.x
- Back up the data directory first. Migrations 0021 to 0025 run on first start; restore that backup to go back.
- Notebook data written with a password-derived key no longer opens. Start such installs from a fresh data directory.
- Comment endpoints are gone (
PUT /api/v1/comments/{id},GET /api/v1/containers/{id}/legacy). Remove any client or script that calls them. - Each browser clears its local note cache and unsent edits once on first load. Send pending edits before upgrading.
- Administrators that also held notes become everyday accounts. If the log then shows
no_active_admin, runkynotes-server user add --admin. - Stop the server before
user add,quota set,bootstrap-admin,integrity-checkorconsistency-check. - Source installs without
docker-compose.build.ymlinCOMPOSE_FILE: run the snippet in that file once beforeup -d.
Changes
- Fixed: two concurrent account recoveries with one code could both succeed; now only the first does.
Resolving a conflict now reaches other clients' sync. A sync page, conflict list, notification list
or pending-sync list with a row the server cannot read now fails instead of quietly leaving it out,
and a conflicting save whose copy fails to store answers 500 instead of reporting a kept copy. - A server killed by SIGKILL, out-of-memory or a crash no longer leaves a lock that stops it from
starting again.user add,quota set,bootstrap-admin,integrity-checkandconsistency-check
now refuse to run beside the server: stop it first.restore-data-dirchecks its input and the
copied database before touching the data directory and keeps the previous contents in
.restore-previous-*;copy-data-dirrefuses a non-empty destination or one inside the data
directory.gc --nowrefuses a--retentionit cannot parse instead of treating it as zero. A sealed
capsule restore now also revokes paired devices, share links and pending invitations. The container
health check no longer writes into/data. - Administrator accounts are now separate from everyday accounts. An administrator account manages users,
teams, single sign-on, backups and the audit log, and cannot open notes; an everyday account cannot reach
administration. First-run setup creates one of each. A password an administrator set must be changed at
first sign-in before anything else. Teams an administrator creates belong to an everyday owner, who names
the notebook, and people an administrator adds receive a team's keys only after one of its owners approves
them. With single sign-on, thekynotes.adminrole signs in only to an administrator account. Upgrading
turns any administrator that also held notes into an everyday account with its notes intact; if that leaves
no administrator, the server logsno_active_adminandkynotes-server user add --admincreates one. - Notebooks are keyed only by their own encryption keys, from the moment they are created; no notebook
content is ever sealed or opened with a key derived from your password (KyNotes was never released, so
this is not a migration). The server refuses to store content, a name, an envelope or an upload for a
notebook until its first key exists, and creating a notebook no longer accepts a name. Every write now
carriesX-Kynotes-Key-Scheme: shared-v2.GET /api/v1/containers/{id}/legacyand
PUT /api/v1/comments/{id}are removed. Development data: rows written by earlier builds with a
password-derived key no longer open (start from a fresh data directory), and each browser clears its
local note cache, unsent-edit queue and pending uploads once on its first load of this version
(IndexedDB v6), so development browsers lose unsent local edits once.kynotes-probenow creates a
password-wrapped encryption key for its account and keys its notebook before writing. - Team keys phase 5: personal notebooks now get their own encryption keys, like team notebooks, so the
server can no longer read them and changing your password no longer makes them unreadable. Each
notebook gets its key when you create it. A one-time recovery code, shown once in your browser, gets your
key back on a new browser when no other browser has it; the server keeps only a copy it cannot open.
An administrator password reset no longer deletes your encryption key. If you lose every browser and
the code, Settings can reset your key, and your personal notebooks are lost. Writing now needs your
encryption key on that browser: accounts still on an administrator-set password change it first, and
single sign-on accounts save a recovery code before their personal notebooks get keys. Single sign-on
no longer asks for a "master password": nothing it would unlock exists. An account linked to KySignOn
never gets a password copy of its key, including through a reset from a local session. An administrator
password reset also revokes the account's paired device credentials. Team member management and "New
team notebook" show only to team owners and admins. The creator of a notebook whose key or name failed
to set up can delete it at any time, as long as it holds nothing. Creating a notebook in a team with
other members no longer fails. After a reset, edits that were waiting for a notebook's key are never
sent; Settings lists them under Unsent edits for export. A reset whose answer never reached the browser
is explained on the next load. Database migration 0025. - Team keys phase 3c: link a new browser to your account from one you already use. Both screens
show a six-digit check code; you type the code from the new browser into the one you already use,
and your encryption key moves only after you confirm it matches on both. KyNotes relays it
encrypted. Accounts that sign in only through single sign-on can now set up an encryption key
(confirmed with KySignOn), receive team keys, and, as team owners, share them with "Share keys".
Browsers on HTTPS store your key encrypted under a browser key that pages cannot export; this does
not protect it from someone who can read the browser's profile on disk, so use "Forget this device"
on shared computers (plain-HTTP sites store it unencrypted, and Settings says so). "Forget this
device" keeps unsent edits until they are sent or discarded. A failed local cache write no longer
blocks sending an edit. On an account that signs in through KySignOn, changing a password an
administrator set needs a KySignOn confirmation. Changing your password signs out your other
sessions and revokes your paired device credentials. Link requests are limited at the device-pairing
rate (ratelimit.pairing_per_hour, own bucket), and collect polls by the new
ratelimit.link_poll_per_minute(default 60;KYNOTES_RATELIMIT_LINK_POLL_PER_MINUTE). Migration
0024addslink_requestsand the step-up scope. - Team keys phase 3b: invitations send a one-time link, and an invitation from someone who can see
your encryption key carries the team's keys, so you can read at once. Team member lists show who
has a key, who is waiting and who has none yet; a member waiting for a key can send an owner a
request. Settings lists the colleague keys your browser trusts, with fingerprints, and re-trusts a
changed one; it also exports (as an unencrypted file) or discards edits stranded for a notebook you
lost. A removed member can be invited again, and removal cancels their pending invitations; a team
admin can remove an admin it invited; invitation expiry is checked as the invitation is accepted;
invitation creation and, in a separate bucket, invitation accepts are rate-limited per account
(ratelimit.invitation_per_hour, default 30); expired
invitations' keys are cleaned up. Refused accepts and admin adds are audited. Migration0023
addsmemberships.invited_by. The browser's local note cache and save queue are now kept per
account, so two accounts signed in on one browser never overwrite or read each other's unsent edits. - Team keys phase 3a: team notebooks are shared end to end. When an owner or admin opens a team
notebook whose members all have encryption keys, their browser creates the notebook key and
shares it; members added later get the notebook's history; removing a member replaces the key
for new content. A member waiting for a key sees the notebook read-only; edits made meanwhile
wait on the device and are saved under the new key when it arrives. Keys are accepted only from
an authenticated sender. Browsers remember colleagues' key fingerprints and ask before trusting
a changed one (Settings shows your own).
GET /api/v1/containersreportssharedGeneration;PATCH /api/v1/containers/{id}takes
keyGeneration(required on a shared notebook,409 already_existsunless current); conflict
listings reportkeyGeneration. - Team keys phase 2 (server rules):
POST /api/v1/containers/{id}/key-rotations, insert-only
envelopes (own identity re-wrap only), member-self envelope writes, envelope writes and rotations
behind a local password step-up (SSO sessions refused), the identity-based save gate for rotated
containers (migration 0022), invitation envelopes and
GET /api/v1/users/{id}/identity.DELETE /api/v1/admin/teams/{id}/members/{userID}now
rotates like owner removal and answers404 not_foundfor a user who is not an active
non-owner member (it answered 204 before).kynotes-probekeeps a random device key in the user
cache dir (-device-keyoverrides) and revokes its device at the end of each run. - Team keys phase 1: each local-password user gets an X25519 identity key, created silently at
login or/setupand wrapped under a key derived from the password (migration 0021). Password
change now re-wraps it; a web bundle from before this release cannot change the password of a
user who has an identity (409 identity_rewrap_required): reload to get th...