Commit Graph
2773 Commits
Author SHA1 Message Date
Dariusz Koryto fc98dd6720 fix(api): accept file uploads on public table forms (#571)
* test(api): cover public table form access, uploads and submissions

Run the public form routes and the owner form settings routes on SQLite
with every migration and filesystem storage: unknown, closed and
deleted-note tokens, password unlock and its rate limit, the fields a
form publishes, stale pending upload cleanup, field validation, and
which uploads a submission may attach.

* fix(api): accept file uploads on public table forms

Public form routes run without a signed-in user, but storing an upload read
the workspace from the auth context, so every valid upload to
POST /api/public/forms/:token/resources failed with a TypeError (HTTP 500).
In the form page the visitor's row was then saved without its file.

- Resource creation accepts the note's workspace explicitly, and the form
  upload passes the form's workspace.
- A form accepts uploads only when it publishes an attachment field, and
  holds at most 50 uploads that were not submitted yet (stale ones are
  still retired after an hour). The limit is checked again after storing,
  so concurrent uploads cannot exceed it.
- A submission marks as used only the files its new row references; a file
  sent in another cell stays pending and is retired like other stale
  uploads instead of being kept forever.
2026-10-15 09:23:42 +08:00
Dariusz Koryto 4754eccb94 fix(api): validate a restore page before writing; test JSON backup restore end to end (#570)
* test(api): cover JSON backup restore end to end

Export a workspace through GET /api/v1/backups/json and restore it into
another installation through the restore routes, on SQLite with every
migration and filesystem storage, the way the ZIP backup does:

- notebooks, notes, revisions, tags, pinned state and files round-trip
  unchanged, and the restored notes are searchable and tagged;
- restoring the same backup twice changes nothing and keeps one object
  per file, and re-restoring a file replaces and removes its old object;
- restoring brings back notes and notebooks deleted after the backup and
  undoes later edits;
- damaged or minimal content falls back safely (empty document, Markdown
  derived from JSON, default title, normalized tags);
- ids used by another workspace, notebooks or notes pointing outside the
  workspace, revisions of another note, invalid file metadata, missing
  notes, empty files and another user's file id are rejected without
  writing;
- only signed-in users can restore.

Raises line coverage of backup-service.ts from 6% to 99% and of
backup-routes.ts from 46% to 94%.

* fix(api): validate a restore page before writing any note

restoreJsonMemos checked that each revision belongs to its note inside the
write loop, so a page whose second note carried another note's revision
returned 400 after the first note had already been restored. The check now
runs for the whole page before anything is written.
2026-10-15 09:23:18 +08:00
Dariusz Koryto 41bce7a126 test(api): cover note trash, user and session management, and object storage settings (#572)
* test(api): cover note trash, restore and permanent deletion

* test(api): cover user management and login session endpoints

Exercise the user and session routes against an in-memory SQLite database with every migration applied and sessions created through real password logins: owner-only access, member provisioning, username and password validation, password resets and account disabling revoking sessions, per-device session listing, renaming and revocation, and per-user storage usage.

* test(api): cover object storage settings and credential handling

Exercise the object storage routes and resolution helpers against a fully migrated in-memory SQLite database with a stubbed S3 endpoint: owner-only access, secret redaction and encryption at rest, input validation, switching providers, per-resource storage resolution, fallback-key credential migration, undecryptable credentials and grouped deletion.
2026-10-15 09:23:06 +08:00
Dariusz Koryto 04fddc7017 ci: run regression tests, type checks and the web build on pull requests (#569)
The full non-E2E suite (`bun run test`) only ran inside the release
workflow, and pull requests only built the Docker image, so a failing test
or type error surfaced at release time. A new Test workflow runs on every
pull request and push to main (Markdown and docs-only changes excluded):

- "Type check and build": `bun run typecheck`, `bun run typecheck:mobile`
  and `bun run build:web`;
- "Regression tests": `bun run test` (bulk and integration suites).

It uses the Bun version pinned in package.json, retries `bun install` like
the other workflows, cancels superseded runs, reads the repository only,
and is limited to this repository so deployment forks spend no runners.
2026-10-15 09:22:54 +08:00
Dariusz Koryto bbe80d18db fix(api): store LF line breaks for multipart image notes; make ACP host tests portable (#568)
* fix(api): store LF line breaks for multipart image notes

multipart/form-data encodes line breaks in text fields as CRLF. Browsers
always do so, and Bun 1.4 now does as well, so notes created through
POST /api/v1/memos/with-image (used by the Web Clipper) were stored with
CRLF line breaks, while every other note uses LF. The route now normalizes
the Markdown field to LF before creating the note.

This also fixes the existing route contract test under Bun 1.4, and a new
test sends a CRLF multipart body like a browser does.

* test(desktop): make ACP host tests independent of the machine and Bun version

- The ACP command allow-list test checked that a missing command is not
  installed, but on macOS the resolver also looks in /opt/homebrew/bin and
  /usr/local/bin, so it failed on any machine with that command installed.
  The test now only sees its temporary directory.
- The fake WorkBuddy agent started its account API without a port during
  probes and chats. Bun 1.3 then listened on a random port, while Bun 1.4,
  like Node, rejects port NaN, so six WorkBuddy session tests hung until
  their timeout. Like WorkBuddy itself, the fake agent now serves the
  account API only when started with a port.
2026-10-15 09:22:42 +08:00
Dariusz Koryto 9bb3218c03 feat(templates): show unedited default templates in the current UI language (#563)
* feat(templates): show unedited default templates in the current UI language

Default templates are stored in the language of the workspace's first
sign-in, so switching the UI language left them in that language. While a
default template still equals one of its seeded translations, the web
template center and the Android template picker now show it in the current
UI language, and using it creates the note in that language. Templates the
user created or edited are shown and used exactly as stored.

POST /api/v1/templates/:id/use accepts an optional `locale`; without it the
stored template is used as before, so MCP, agents and older clients are
unaffected.

* fix(templates): edit the stored template and stop localizing retagged defaults

- The template center now keeps each card's stored template next to its
  display translation. Editing starts from the stored fields, so saving a
  name-only change in another UI language no longer writes the translated
  title, description and Markdown.
- A default template whose tags differ from its seeded tags is treated as
  edited and is no longer localized.
- Add regression tests for the name-only edit and changed tags.
2026-10-15 09:10:38 +08:00
tianma-if 2977f07bdb fix(desktop): support bundled WorkBuddy credential codec exports 2026-10-15 01:20:12 +08:00
Dariusz Koryto 4dfa1546d7 ci(mobile): retry bun install in mobile build workflow (#564)
Mirror the desktop-build retry loop so a transient tarball download
failure no longer fails the whole Android build.
2026-10-15 00:12:28 +08:00
Dariusz Koryto 6f50d1a80a ci: retry bun install across remaining workflows (#565)
Mirror the retry loop already used in desktop-build.yml for every remaining one-shot 'bun install --frozen-lockfile' step so transient registry or network failures (e.g. a failed mermaid tarball download) no longer fail the whole run. deploy-tools.yml gains shell: bash because its matrix includes windows-latest; sync-edgeever-upstream.yml uses break on success so the following verification commands still run.
2026-10-14 23:59:50 +08:00
Dariusz Koryto b3f4dfda2b feat(workspace): localize default notebooks and welcome note at first sign-in (#562)
* feat(workspace): localize default notebooks and welcome note at first sign-in

A new installation always created its five default notebooks, welcome
note and note templates in Chinese, whatever the interface language.
Members added by the owner got notebooks and templates in the owner's
language instead of their own.

The seed data is now localized once, at the first sign-in of the
workspace's user, using the UI locale the client sends with the login
request (Web and Android send it; other clients fall back to
Accept-Language, and unsupported languages to English).

Migration 0070 marks the default workspace as waiting for this only on
an installation nobody has used yet: no users, no notes beyond the
welcome note, no edits to it, no extra notebooks, revisions or
resources. Existing installations keep their data unchanged. Member
workspaces created by the owner are marked when created.

The sign-in localizes notebook names, templates, the welcome note and
its search document in one transaction that also clears the mark, and
replaces only values that still equal a seeded translation. A failed
attempt leaves the mark for the next sign-in to retry, and a second
sign-in changes nothing. The demo clears the mark so its bilingual seed
stays as it is.

Refs #483

* fix(workspace): guard seed inserts and title-only welcome edits during localization

- Default template and AI prompt inserts in the first-sign-in batch now
  require the pending marker, so a delayed concurrent sign-in cannot
  recreate seeds removed after the faster sign-in finished.
- The welcome note is treated as untouched only while it keeps the seeded
  title, the system actor, the seed content hash, and revision 0, so a
  title-only edit is no longer overwritten.
- Add regression tests for both cases.

Refs #483
2026-10-14 20:45:42 +08:00
tianma-if 3c77c67155 fix(desktop): defer local AI probes until selector opens
Record adapter process lifecycle diagnostics to correlate transient Windows consoles.

Refs #561; Windows device verification remains pending.
2026-10-14 17:53:03 +08:00
tianma-if 36c8c4171b docs: align READMEs with recent releases across locales 2026-10-14 13:13:52 +08:00
tianma-if 2ba1e8e70e chore: release v1.118.0 [skip ci] 2026-10-14 11:03:01 +08:00
tianma-if 0be992d650 test(web): account for deferred notebook sharing translations 2026-10-14 11:01:14 +08:00
tianma-if 8127802f32 chore: release v1.117.0 [skip ci] 2026-10-14 10:56:01 +08:00
tianma-if 21d291dca5 test(desktop): avoid filesystem order assumptions in share recovery 2026-10-14 10:54:27 +08:00
tianma-if c6a5eeef5d chore: release v1.116.0 [skip ci] 2026-10-14 10:51:28 +08:00
tianma-if 4c592d68a1 fix(ai): clarify current note context for local agents 2026-10-14 10:48:42 +08:00
tianma-if c78f17a800 fix(desktop): restore WorkBuddy sign-in after connection failure 2026-10-14 10:40:53 +08:00
tianma-if d18c63618f fix(desktop): persist failed share imports across restarts 2026-10-14 10:33:10 +08:00
tianma-if 82fa24c3a0 fix(sharing): align memo sharing actions and allow revocation retries 2026-10-14 10:27:01 +08:00
tianma-if 043752546f fix(web): correct sharing dialog initial focus and close button rings 2026-10-14 10:12:25 +08:00
tianma-if 590150d3ea fix(web): clarify sharing states and close dialogs on navigation 2026-10-14 10:02:58 +08:00
tianma-if 80c83023cf refactor(sharing): streamline share dialogs and create links on open 2026-10-14 09:39:31 +08:00
tianma-if 29bb511259 feat(sharing): recover encrypted passwords across devices 2026-10-14 09:27:13 +08:00
tianma-if 6d9469c058 refactor(web): streamline share dialog layout and password controls 2026-10-14 00:13:07 +08:00
tianma-if eda356a824 fix(sharing): require password verification for logged-in users 2026-10-13 23:46:32 +08:00
tianma-if e711bb5880 fix(web): simplify shared note and notebook indicators 2026-10-13 23:35:20 +08:00
tianma-if a78586b716 feat(sharing): add password protection for notebook shares 2026-10-13 23:24:17 +08:00
tianma-if 411f668edf fix(release): allow slow Play APK transfers to complete 2026-10-13 21:58:39 +08:00
tianma-if a7f05b439c fix(web): clarify share management layout and notebook icon 2026-10-13 21:56:08 +08:00
tianma-if 62390b218f feat(web): turn shared notebooks into a navigable website 2026-10-13 21:45:58 +08:00
tianma-if cdcc77af5e fix(ui): use softer neutral colors for solid buttons and share link 2026-10-13 21:40:23 +08:00
tianma-if 36f081ea09 fix: reuse isolated store dependency caches for unchanged locks 2026-10-13 21:38:39 +08:00
tianma-if a6d80e994e docs: align UI color guidance with existing neutral palette 2026-10-13 21:30:04 +08:00
tianma-if 5b2e69eab3 fix: allow slow dependency downloads during Google Play delivery 2026-10-13 19:59:59 +08:00
tianma-if 13f8b3f407 feat: share notebooks recursively with live public reading
Add notebook-level share management, directory navigation, and live subtree checks for notes and attachments. Include migration and access-boundary regression tests.

Refs #551
2026-10-13 19:27:16 +08:00
tianma-if a8d845e9cb fix(i18n): shorten inbox deletion hint 2026-10-13 19:23:25 +08:00
tianma-if a05e4f8d39 fix: resume replacement release drafts after reserving versions 2026-10-13 18:29:39 +08:00
tianma-if 30a4ab08ca chore: release v1.115.0 [skip ci] 2026-10-13 18:04:02 +08:00
tianma-if cc0f21ddbd fix: account for new Japanese strings in deferred locale budget 2026-10-13 17:59:49 +08:00
tianma-if ccc8a57129 chore: release v1.114.0 [skip ci] 2026-10-13 17:55:08 +08:00
tianma-if d8264b91e3 docs: split plugin UI, commands, and panels into separate API sections 2026-10-13 17:46:21 +08:00
tianma-if 91f1887c33 fix(ai): surface safe companion failure diagnostics
Preserve HTTP status and fixed failure categories for direct and proxied agent requests, display diagnostics beside failed turns, and prevent AI SDK error logging from exposing request data.

Refs #555
2026-10-13 17:35:33 +08:00
tianma-if 1c234a463c fix: clarify used storage labels and simplify member descriptions
Refs #553
2026-10-13 17:17:23 +08:00
tianma-if 7bbde189f8 feat: show instance and per-account attachment storage usage
Add owner-only attachment summaries and a compact member management table. Keep personal attachment statistics unchanged and exclude Trash from usage totals.

Refs #553
2026-10-13 17:12:04 +08:00
tianma-if f682fbcb33 fix: refine inline code styling and improve region visibility 2026-10-13 16:15:38 +08:00
tianma-if fda8cf9ba6 fix(desktop): preserve attachment downloads behind navigation guard 2026-10-13 14:21:59 +08:00
tianma-if c7c4a5e329 chore: release v1.113.0 [skip ci] 2026-10-13 14:15:15 +08:00
tianma-if 55d56957a0 fix: neutralize inline code colors and refine prose palette names 2026-10-13 14:06:34 +08:00