## Summary
This is a backend-only workaround for native/mobile sessions expiring
much earlier than the normal AFFiNE auth session.
Native JWT-backed sessions now use the existing `auth.session.ttl`
instead of the hard-coded 15-minute TTL.
No database migration, no new config, and no mobile client changes are
required.
## Background / Investigation
PR #15060 introduced native session exchange and JWT-backed native
sessions for mobile/desktop clients.
Relevant code introduced there:
- `packages/backend/server/src/core/auth/session-issuer.ts`
- Native clients no longer receive normal auth cookies.
- `SessionIssuer` clears cookies for native clients and returns a native
session exchange code instead.
- `packages/backend/server/src/core/auth/native-exchange.ts`
- Native clients exchange the one-time code for a JWT-backed session
token.
- `packages/backend/server/src/core/auth/jwt-session.ts`
- The JWT session implementation was introduced with:
- `const JWT_SESSION_TTL = 15 * 60`
- `expiresIn: JWT_SESSION_TTL`
- normal `jwt.verify(...)` expiration enforcement
That means a native/mobile client that does not reconnect and
exchange/sign in again within 15 minutes can lose backend auth even
though the DB-backed AFFiNE user session is still valid for the normal
app session TTL, currently 15 days by default.
Web does not hit this path because web keeps using the normal
cookie-backed session issued by `AuthService`, whose expiration is based
on `auth.session.ttl`.
## Related Issues / PRs Checked
- Source PR: #15060
- Introduced native session exchange, JWT-backed sessions, native token
storage, and websocket JWT support.
- This PR appears to be the source of the hard-coded 15-minute native
JWT TTL behavior.
I did not find a public issue that directly reports "native JWT expires
after 15 minutes".
## What Changed
- Removed the hard-coded 15-minute native JWT TTL.
- Updated `JwtSessionService.sign()` to issue native JWTs with
`auth.session.ttl`.
- Kept `JwtSessionService.verify()` on normal JWT expiration
verification, so existing JWTs that already expired under the previous
15-minute `exp` need to be refreshed by signing in again.
- Kept the existing DB-backed session lookup:
- sign-out still revokes the native JWT by deleting the backing session
- expired/deleted DB sessions still reject the JWT
## Why This Is A Workaround
A more complete long-term design would add a true refresh-token flow for
native clients, likely with persisted refresh tokens,
rotation/revocation semantics, and database changes.
This PR intentionally avoids that larger design. It restores the
expected mobile login lifetime for newly issued native JWTs by aligning
native JWT lifetime with the existing app session lifetime, while
preserving the current native exchange model, Keychain/Keystore storage,
and revoke-by-session behavior.
## Compatibility
- Backend only
- No DB schema change
- No mobile app change
- No new config
- Existing native JWTs that already expired under the old 15-minute
`exp` will still require signing in again.
- Newly issued native JWTs use `auth.session.ttl`.
## Verification
Latest verification after removing the extra native JWT TTL config:
- JWT session tests: 4 passed
- `yarn typecheck`: passed
- `lint-staged`: passed via `corepack yarn`
- `lint:ox`: passed via `corepack yarn`
Earlier broader checks on this branch also passed selected auth tests
and the websocket JWT auth subset.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Session login tokens now follow the configured session lifetime, so
expiration behavior can be adjusted through app settings.
* **Bug Fixes**
* Improved consistency between token expiration and session expiry
checks.
* Added coverage for cases where a session is missing, expired, or the
session lifetime changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 -->
## 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 -->
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 -->
Fix https://github.com/toeverything/AFFiNE/issues/14059
With the help of Claude Opus 4.5
Improve handling of keyCode fallback for non-standard keyboards by only
applying it when modifier keys are pressed. This change prevents
incorrect fallback behavior for non-ASCII characters, ensuring users can
type intended characters without triggering shortcuts.
After
https://github.com/user-attachments/assets/00ab4fb2-4bc2-4ca7-a284-9782686d298c
Event dump for Cyrillic x
```json
{
"key": "х",
"keyCode": 219,
"which": 219,
"code": "BracketLeft",
"location": 0,
"altKey": false,
"ctrlKey": false,
"metaKey": false,
"shiftKey": false,
"repeat": false
}
```
blocksuite commit
https://github.com/toeverything/blocksuite/commit/4c0d39890fb65e8de974169fa1c96b038f6d4a83#diff-68c46455e0eece88312235df85f8ce27ae254efccde6fb987f2505180730bd8c
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Refined keyboard input handling to properly support non-ASCII
characters (e.g., Cyrillic, Greek) by ensuring user-typed characters are
preserved instead of inadvertently triggering keyboard shortcuts. The
fix maintains keyboard shortcut functionality while improving
compatibility with international keyboards and input methods.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->