互联同步是什么What is encrypted sync
解决什么问题
The problem it solves
Novara 的全部数据都在一台 Windows 电脑上。想在路上查一条密码、勾一个待办、补一段记录,就需要第二块屏幕看到同一份库。互联同步解决的就是这件事:把一台你自己的机器(Windows 电脑、NAS 或 VPS)变成小小的中转站,桌面端与手机浏览器各自与它交换数据。
All of Novara's data lives on one Windows computer. To look up a password, tick a to-do or add a record while on the move, a second screen needs to see the same vault. That is exactly what encrypted sync solves: turn one of your own machines (a Windows PC, a NAS or a VPS) into a small relay, and both the desktop app and your phone's browser exchange data with it.
先说清边界:如果你不需要跨设备,完全可以不装。Novara 的全部本地功能都不依赖服务端,也没有任何"必须在线才能用"的核心功能。
First, the boundary: if you do not need cross-device access, you can simply skip this. Every local feature works without a server, and no core feature requires being online.
三方角色,各持什么
Three parties and what each holds
| 角色 | 持有 | 禁止 |
|---|---|---|
| PC 客户端 | 锁密码、SpaceKey、明文库(权威副本) | 把明文写入任何导出物 |
| NovaraSync 服务端 | 空间元数据、keywrap 密文、版本 blob | 解密、持有密钥、记录敏感信息 |
| Web-PWA(手机/浏览器) | 当前解锁会话内的 SpaceKey 与明文 | 任何持久化(localStorage / IndexedDB / Cookie) |
| Party | Holds | Forbidden |
|---|---|---|
| PC client | Lock password, SpaceKey, plaintext vault (authoritative copy) | Writing plaintext into any export |
| NovaraSync server | Space metadata, keywrap ciphertext, version blobs | Decrypting, holding keys, logging sensitive content |
| Web-PWA (phone/browser) | SpaceKey and plaintext inside the current unlocked session | Any persistence (localStorage / IndexedDB / cookies) |
一句话概括:服务器本质是带版本历史的加密文件存储。它读取信封元数据来裁决冲突与配额,但从不解析载荷内容。
In one sentence: the server is essentially an encrypted file store with version history. It reads envelope metadata to arbitrate conflicts and quotas, but never parses payload contents.
端到端加密意味着什么
What end-to-end encryption means here
- 数据在离开电脑之前就已加密(v4 容器,AES-256-GCM)。
- 服务器只搬运密文 blob、keywrap 记录与必要元数据——它打不开任何内容。
- 真正的钥匙 SpaceKey 由第一台配对的 PC 生成,服务器从不持有它的明文形态。
- 解密只发生在你授权的客户端运行时里:桌面端内存,或手机浏览器内存。
- Data is encrypted before it leaves the computer (v4 container, AES-256-GCM).
- The server relays only ciphertext blobs, keywrap records and necessary metadata — it cannot open anything.
- The real key, the SpaceKey, is generated by the first paired PC; the server never holds it in plaintext form.
- Decryption happens only inside a client runtime you authorize: desktop memory, or your phone browser's memory.
空间密钥的封装记录(keywrap)虽然存放在服务器上,但它是被你的解锁密码加密过的——没有密码,服务器手里那份记录只是一段解不开的密文。
Although the space key's wrapping record (keywrap) sits on the server, it is encrypted with your lock password — without that password, the record on the server is just ciphertext that will not open.
断网了会怎样
What if the connection drops
你的 Windows 本地库是权威副本。服务器关机、隧道中断、域名没续费,都只意味着"暂时不能跨设备"——桌面端照常整理、搜索、编辑。连接恢复后由同步引擎按版本补齐,不会丢改动。
Your Windows local vault is the authoritative copy. A powered-off server, a broken tunnel or an expired domain only means "no cross-device access for now" — the desktop keeps organizing, searching and editing as usual. When the connection returns, the sync engine reconciles by version; nothing is lost.
Web-PWA 是受控入口,不是官方云。Novara 不运营任何接收明文资料的云服务,也没有账号体系——服务器是你自己的,密钥也在你手里。
The Web-PWA is a controlled entrance, not an official cloud. Novara runs no cloud service that accepts plaintext, and there is no account system — the server is yours and so are the keys.
本篇的几个词
A few words used in this guide
- 空间(Space):一份同步数据的容器,由一次性 CLI 命令创建,拥有独立的 space id。
- 配对(Pairing):把一台设备接入空间,需要 space id 与 enrollment secret。
- SpaceKey(空间密钥):256-bit 随机密钥,派生每一版数据的加密密钥;由第一台配对的 PC 生成。
- enrollment secret(配对密钥):建空间时打印的一次性凭据,用于设备注册。
- 只读令牌:给手机浏览用的 24 字符凭据,只能读,随时可作废。
- 编辑凭据:给 Web 编辑端的凭据,可修改数据,对应一台虚拟的 "web-editor" 设备。
- 墓碑:删除操作的同步标记,保证"删了"这件事也能同步到所有设备。
- Space: the container for one sync dataset, created by a one-time CLI command, with its own space id.
- Pairing: joining a device to a space; requires the space id and the enrollment secret.
- SpaceKey: a 256-bit random key from which every version's encryption key is derived; generated by the first paired PC.
- Enrollment secret: the one-time credential printed when the space is created, used for device registration.
- Read-only token: a 24-character credential for phone browsing — read access only, revocable at any time.
- Edit credentials: credentials for the web editor that may modify data, mapped to a virtual "web-editor" device.
- Tombstone: the sync marker for deletion, ensuring "it was deleted" reaches every device too.
常见问题
FAQ
会不会哪天变成收费的云服务?
不会。架构上就没有官方云:服务器是你自己的,Novara 官方既没有你的数据,也没有你的密钥。自托管不是低配版,是设计决策。
互联同步会改变我的本地库格式吗?
不会。同步载荷本身就是一个标准 v4 加密备份容器,本地库格式、快照格式、同步契约三者互不干扰。
第二台电脑加入要重新建空间吗?
不要。空间只有一个,第二台设备走"加入已有空间"的配对,需要填空间密钥——见《加入更多设备》。
Will this become a paid cloud service one day?
No. There is no official cloud in the architecture: the server is yours, and Novara holds neither your data nor your keys. Self-hosting is not the budget tier — it is the design decision.
Does encrypted sync change my local vault format?
No. The sync payload is itself a standard v4 encrypted backup container; the local vault format, the snapshot format and the sync contract never interfere with each other.
Does a second computer need a new space?
No. There is only one space; the second device pairs by "joining an existing space" and needs the space key — see "Add more devices".
服务器上到底有什么What the server actually holds
完整清单
The complete list
下表逐项列出 NovaraSync 服务端与你的数据的关系。事实来源是随代码维护的服务端安全基线(deploy/SECURITY.md),任何实现违反其中一条即视为缺陷。
The table below lists, item by item, how the NovaraSync server relates to your data. The source of truth is the server security baseline maintained with the code (deploy/SECURITY.md); any implementation violating one line of it is a defect.
| 项 | 服务器 |
|---|---|
| 同步密文容器(blob) | 持有——密文,AES-256-GCM,服务器无法解密 |
| keywrap 记录 | 持有——密文:被你的解锁密码封装过的 SpaceKey |
| 设备令牌 / 只读令牌 | 只持有 SHA-256 哈希(明文只在签发响应中出现一次) |
| enrollment secret | 只持有 SHA-256 |
| SpaceKey | 永不持有——由首次配对的 PC 生成,仅以 keywrap 密文形态经手 |
| 明文数据、库密码、口令 | 永不持有、永不接触 |
| Item | Server |
|---|---|
| Sync ciphertext containers (blobs) | Holds — ciphertext, AES-256-GCM; the server cannot decrypt it |
| Keywrap records | Holds — ciphertext: your SpaceKey wrapped with your lock password |
| Device tokens / read-only tokens | Holds only SHA-256 hashes (plaintext appears exactly once, in the issuance response) |
| Enrollment secret | Holds only the SHA-256 |
| SpaceKey | Never held — generated by the first paired PC and only ever handled as keywrap ciphertext |
| Plaintext data, vault password, passphrases | Never held, never touched |
日志纪律
Log discipline
服务端的安全基线把日志脱敏列为最高优先级禁令:Authorization 头(设备令牌、只读令牌)、blob 内容、enrollment secret、令牌与编辑凭据明文,永远不允许写进日志或错误信息。
The server security baseline makes log redaction a top-priority prohibition: Authorization headers (device tokens, read-only tokens), blob contents, enrollment secrets, and token or edit-credential plaintext are never allowed into logs or error messages.
审计与日志只记录元数据:哪个空间、哪个设备、什么动作、结果、字节数、时间戳。当前版本的服务端甚至没有任何应用层日志——这条约束是写给未来的:任何新增日志都不得把上述内容带出来,调试日志只允许记录形状(长度、哈希前几位、状态码),不允许记录内容。
Auditing and logs record metadata only: which space, which device, what action, the result, byte counts, timestamps. The current server version ships no application-level log at all — the constraint is written for the future: any new log line must not carry the items above; debug logs may record shape only (lengths, hash prefixes, status codes), never content.
这些数据存在哪
Where this data lives
| 内容 | 位置 |
|---|---|
| 配置元数据 | <数据目录>/novara-sync.db |
| 每个版本的密文 | <数据目录>/spaces/<空间ID>/blobs/<版本号> |
| 设备令牌与 keywrap 记录 | 同一个库内(只有密文与哈希) |
| 手机端页面 | 服务端目录下的 Novara.Web/ |
| Content | Location |
|---|---|
| Configuration metadata | <data directory>/novara-sync.db |
| Ciphertext of each version | <data directory>/spaces/<space id>/blobs/<version> |
| Device tokens and keywrap records | Inside the same database (ciphertext and hashes only) |
| Phone-side pages | Novara.Web/ under the server directory |
怎么自己核对
How to check it yourself
- 全部 /api 响应由服务端设置
Cache-Control: no-store——绕过反代直连同样成立。 - 访问
/web(不带尾斜杠)的跳转是相对地址,不由请求的 Host 构造——看不到内网地址即正确。 - CSP 等安全响应头由服务端对每个响应发出,走不经反代的隧道(如临时验收通道)时同样存在。
- 整个数据目录可以直接复制走——它全是密文;但仍建议按敏感文件对待。
- All /api responses carry
Cache-Control: no-storeset by the server — true even when bypassing the reverse proxy. - The redirect for
/web(no trailing slash) is a relative address, not built from the request Host — if you see no internal address, it is correct. - Security response headers such as CSP are emitted by the server on every response — present even through tunnels that bypass the reverse proxy (like a temporary review channel).
- The whole data directory can be copied away directly — it is all ciphertext; still, treat it as sensitive files.
配对第一台设备Pair the first device
开始之前
Before you start
- 服务器已经跑起来(自建服务端篇的任意一条路径都行,Windows 直跑最快)。
- 你手上已有 space id 与 enrollment secret——建空间那一刻打印的两串字符。
- 桌面端为 Novara 9.0 或更高版本。
- The server is running (any path from the self-hosting guide works; Windows direct-run is fastest).
- You have the space id and the enrollment secret — the two strings printed when the space was created.
- The desktop app is Novara 9.0 or later.
space id 与 enrollment secret 只在建空间时显示一次,服务端只存哈希、找不回来。当场收好。
The space id and enrollment secret are shown exactly once, when the space is created; the server stores only hashes and cannot recover them. Save them on the spot.
配对步骤
Pairing steps
- 打开配对弹窗Novara 桌面端 → 汉堡菜单 → 工具 → 互联同步 → 配对。
- 填服务器地址对外访问地址,例如
https://sync.example.com。必须 https;只有本机回环地址允许 http。 - 填 space id建空间命令输出的第一串字符,原样粘贴。
- 填 enrollment secret建空间命令输出的第二串字符,原样粘贴。
- 空间密钥留空,点配对本机名称随意(用于在设备列表里认出这台机器)。配对成功会弹出「妥善保存同步空间密钥」。
- Open the pairing dialogNovara desktop → hamburger menu → Tools → Encrypted sync → Pair.
- Fill the server addressThe public address, e.g.
https://sync.example.com. Must be https; only loopback addresses may use http. - Fill the space idThe first string printed by the space-create command, pasted as-is.
- Fill the enrollment secretThe second string printed by the space-create command, pasted as-is.
- Leave the space key empty, click PairThe local device name is free-form (used to recognize this machine in the device list). On success a dialog says "store the sync space key safely".
空间密钥为什么留空
Why the space key stays empty
空间密钥(SpaceKey)留空是刻意的,不是遗漏:第一台配对的设备自己生成它,服务端从不持有。
Leaving the SpaceKey empty is deliberate, not an omission: the first paired device generates it itself; the server never holds it.
配对成功的那一刻,桌面端生成一个 256-bit 随机 SpaceKey,用本机库密码封装后上传(这就是 keywrap 记录),随后弹出「妥善保存同步空间密钥」。这把钥匙是后续设备加入的唯一凭据——服务端只有密文形态,找不回明文。
At the moment pairing succeeds, the desktop generates a 256-bit random SpaceKey, wraps it with this machine's vault password and uploads it (that is the keywrap record), then shows "store the sync space key safely". This key is the only credential for later devices to join — the server has only the ciphertext form and cannot recover the plaintext.
所以配对弹窗的规则是:留空 = 新建空间(第一台设备),填写 = 加入已有空间(第二台及以后)。两台设备的库密码通常不同,互解不了对方的封装记录,因此空间密钥只能从创建它的那台设备界面上抄。
So the pairing dialog's rule is: empty = create the space (first device), filled = join an existing space (second and later). Two machines usually have different vault passwords and cannot unwrap each other's keywrap records, so the space key can only be read from the device that created it.
一个容易卡死的坑:同一数据目录
One easy trap: the same data directory
建空间的 CLI 命令会把凭据写进 NOVARA_SYNC_DATA 环境变量指向的目录(未设置时用当前工作目录下的 data)。它必须与服务端用的数据目录是同一个——否则凭据落进另一个目录,服务端看不到这个空间,配对必然失败。
The space-create CLI writes credentials into the directory pointed to by the NOVARA_SYNC_DATA environment variable (when unset, data under the current working directory). It must be the same directory the server uses — otherwise the credentials land elsewhere, the server never sees the space, and pairing fails by construction.
Windows 安装包自带的 1-建空间.cmd 与 2-启动服务端.cmd 已经把这一点处理好:两者都指向 %LOCALAPPDATA%\Novara\Server\data。Docker Compose 路径中,docker compose run --rm novara-sync space create 挂载的也是与服务端相同的 ./data。
The bundled 1-建空间.cmd and 2-启动服务端.cmd scripts already handle this: both point to %LOCALAPPDATA%\Novara\Server\data. On the Docker Compose path, docker compose run --rm novara-sync space create mounts the same ./data as the server.
配对之后
After pairing
配对完成后,同一张互联同步卡片上可以生成只读令牌与编辑凭据给手机(见《手机只读访问》),也可以在设备中心看到这台机器并随时管理(见《加入更多设备》)。第一轮同步会把本地库完整推送上去。
Once paired, the same encrypted-sync card can issue a read-only token and edit credentials for your phone (see "Read-only mobile access"), and this machine appears in the device center for management at any time (see "Add more devices"). The first sync round pushes the whole local vault up.
加入更多设备Add more devices
先读这段
Read this first
space id、enrollment secret、SpaceKey——三样都给等于给了读权限。拿到这三样的人可以注册设备、拉取全部密文并用自己的密码解封。分享对象请想清楚;用完可在设备中心撤销。
The space id, the enrollment secret and the SpaceKey — handing over all three equals handing over read access. Anyone holding them can register a device, pull the full ciphertext and unwrap it with their own password. Think before sharing; revoke in the device center when done.
第二台设备需要什么
What a second device needs
| 凭据 | 从哪来 |
|---|---|
| space id | 与首台设备相同(建空间时的输出) |
| enrollment secret | 与首台设备相同;若已作废可在服务端用 rotate-secret 换新 |
| SpaceKey(空间密钥) | 只能来自创建它的那台设备——服务端取不回 |
| Credential | Where it comes from |
|---|---|
| Space id | The same as the first device (printed at space creation) |
| Enrollment secret | The same as the first device; if revoked, renew it on the server with rotate-secret |
| SpaceKey | Only from the device that created it — the server cannot recover it |
配对流程与首台设备完全相同,唯一区别是空间密钥一栏填写创建设备上显示的那把。
The pairing flow is identical to the first device; the only difference is that the space key field carries the key shown on the creating device.
空间密钥在哪看
Where to see the space key
- 在已配对的设备上:设置 → 互联同步 → 查看空间密钥(需要输入本机锁密码)。
- 或导入之前导出的
.novakey备份文件——只读展示、可复制,不会自动写入任何配置。
- On a paired device: Settings → Encrypted sync → View space key (asks for this machine's lock password).
- Or import a previously exported
.novakeybackup file — display-only and copyable; it never writes itself into any configuration.
.novakey 文件的内容是一条 keywrap 记录(JSON),不是 v4 加密容器——它不能当数据库备份导入,扩展名刻意与 .novaenc 区分就是这个原因。文件对应的口令是导出那台设备的锁密码:改过密码后,旧文件仍对应旧密码,这是备份文件的固有性质。
A .novakey file contains a keywrap record (JSON), not a v4 encrypted container — it cannot be imported as a database backup; the extension is deliberately distinct from .novaenc for exactly this reason. The file's passphrase is the exporting device's lock password at that time: after a password change, the old file still corresponds to the old password — inherent to backup files.
设备令牌放在哪
Where device tokens live
配对成功后,本机的设备令牌存放在 Windows 凭据保险箱(PasswordVault,经 DPAPI 保护),绑定当前 Windows 用户——换电脑、换用户都需要重新配对,令牌不会跟着文件走。SpaceKey 同样只在内存与凭据保险箱中,不随同步数据落盘。
After successful pairing, this machine's device token is stored in the Windows Credential Locker (PasswordVault, DPAPI-protected), bound to the current Windows user — a new computer or a new user means pairing again; the token does not travel with files. The SpaceKey likewise lives only in memory and the credential locker; it never hits disk with sync data.
设备中心:撤销与重置是两件事
Device center: revoke and reset are different
| 动作 | 语义 |
|---|---|
| 撤销设备 | 软删除:设备行保留并标记「已撤销」,该设备立即失去同步与读取;想恢复必须重新配对(需要空间密钥) |
| 重置令牌 | 保留设备行、换发新令牌;旧令牌立即失效,该设备被登出——用于"强制某台设备下线再重新登录" |
| Action | Meaning |
|---|---|
| Revoke device | Soft delete: the device row stays, marked "revoked"; the device immediately loses sync and read access; rejoining requires pairing again (with the space key) |
| Reset token | Keeps the device row and issues a new token; the old token dies instantly and the device is signed out — for "force a device offline, then sign back in" |
当前正在使用的设备不能撤销自己——服务端会直接拒绝,界面上本机那一行也只提供「重置令牌」。这不是 UI 限制,是防呆:撤销自己只会让你立刻失联,且恢复还要重新配对。
The device you are currently using cannot revoke itself — the server refuses outright, and the local row in the UI only offers "reset token". Not a UI limitation but a guardrail: revoking yourself would cut you off on the spot, and rejoining would require pairing again.
设备不受数量限制。电脑与 Web 编辑端各算一台,都能在设备中心单独管理。
There is no device count limit. Computers and the web editor each count as one device, each manageable individually in the device center.
常见问题
FAQ
忘了空间密钥怎么办?
服务端只有密文,取不回。唯一来源是创建它的那台设备:设置 → 查看空间密钥;或导入之前导出的 .novakey。两样都没有时,只能停用这个空间、建一个新空间重新配对。
某台设备丢了怎么办?
在设备中心撤销它。撤销立即生效——那台设备下一次请求就会被拒绝。
I forgot the space key — what now?
The server holds only ciphertext and cannot recover it. The only source is the device that created it: Settings → View space key; or import a previously exported .novakey. With neither, the only path is to retire this space, create a new one and pair afresh.
A device was lost — what do I do?
Revoke it in the device center. Revocation is immediate — that device's very next request is refused.
同步状态与冲突Sync status and conflicts
什么时候同步
When sync runs
桌面端的同步由总开关控制,按你在设置里选的频率自动运行;每次写盘也会按需触发。想立刻推一轮,点互联同步卡片上的「立即同步」。所有动作都写进本机审计日志(不含任何明文与凭据)。
The desktop's sync is governed by the master switch and runs automatically at the interval you pick in settings; writing to disk can also trigger it as needed. To push a round right now, click "Sync now" on the encrypted-sync card. Every action lands in the local audit log (never any plaintext or credentials).
锁定状态下不同步:手动锁、空闲自动锁、Windows 锁屏联动的硬锁都会先暂停同步——锁定期禁网是硬规则,不会因为"远端有新版本"而绕过。
No sync while locked: the manual lock, the idle auto-lock and the Windows lock-screen linkage all pause sync first — no network while locked is a hard rule, never bypassed because "the server has a newer version".
上传怎么被保护
How uploads are protected
- 每轮上传携带基础版本号(If-Match 语义):我基于第 N 版改的,就声明 N。
- 服务端当前已是 N+1 或更高 → 拒绝并返回
409 version_conflict,附当前版本号(不含明文)。 - 载荷先校验 SHA-256 摘要,再做常量时间 HMAC 比对——元数据被篡改的容器到不了落盘那一步。
- Each upload carries the base version (If-Match semantics): "I edited based on version N" declares N.
- If the server is already at N+1 or higher → it refuses with
409 version_conflict, including the current version number (no plaintext). - The payload's SHA-256 digest is checked first, then a constant-time HMAC comparison — a container with tampered metadata never reaches disk.
落后版本被拒绝后,客户端不会自动用新内容盖回去。冲突是显式的:由你看过差异再决定。
When a stale version is refused, the client does not silently push the newer content over. Conflict is explicit: you inspect the difference and decide.
冲突怎么处理
How a conflict is resolved
桌面端弹出冲突面板时会给出分区级差异摘要(哪些分区在两端各自有改动),然后提供几个出口:
When the desktop opens the conflict panel it shows a per-area diff summary (which areas each side changed), then offers several exits:
- 导出两个版本——把本地版与云端版分别导出成 v4 加密文件,之后自行比较或择一恢复。
- 采用云端版本——放弃本机未上传的改动,拉取云端当前版本。
- 显式强制覆盖——用本地版本覆盖云端,需要二次确认。
- Export both versions — export the local and the cloud version as separate v4 encrypted files; compare or restore either later.
- Take the cloud version — discard the un-pushed local changes and pull the cloud's current version.
- Explicit force overwrite — push the local version over the cloud one; double confirmation required.
Web 端(浏览器编辑)遇到 409 时,你的修改先保留在内存里:可以复制 JSON、导出 .novaenc(默认,电脑端可直接还原)、导出明文 JSON(二次确认)、强制覆盖(二次确认),或放弃本页改动改用云端版本。刷新前有未上传改动时浏览器也会拦截提醒。
On the web side (browser editing), a 409 keeps your edits in memory: you can copy the JSON, export a .novaenc (default; the desktop can restore it directly), export plaintext JSON (double confirmation), force overwrite (double confirmation), or drop this page's changes and take the cloud version. Before a refresh with un-pushed changes, the browser also warns.
版本保留与配额
Retention and quotas
| 项 | 默认值 | 含义 |
|---|---|---|
| 版本保留数 | NOVARA_SYNC_MAX_VERSIONS=10 | 每个空间保留最近 10 版;冲突副本单独计数,不挤占常规版本 |
| 空间配额 | NOVARA_SYNC_QUOTA_BYTES=524288000(500 MiB) | 单空间密文总量上限,超限返回 507 |
| 单次上传上限 | NOVARA_SYNC_MAX_PAYLOAD_BYTES=67108864(64 MiB) | 单次请求载荷上限,超限返回 413 并附上限值 |
| Item | Default | Meaning |
|---|---|---|
| Version retention | NOVARA_SYNC_MAX_VERSIONS=10 | Each space keeps the last 10 versions; conflict copies are counted separately and do not crowd out regular versions |
| Space quota | NOVARA_SYNC_QUOTA_BYTES=524288000 (500 MiB) | Total ciphertext cap per space; over the limit returns 507 |
| Per-upload cap | NOVARA_SYNC_MAX_PAYLOAD_BYTES=67108864 (64 MiB) | Request payload cap; over the limit returns 413 with the limit value |
空间写满时返回 507 quota_exceeded,错误体带 usedBytes 与 limitBytes——"已用多少 / 上限多少"正是你删旧版本或调配额前需要的信息。这些默认值都可以用环境变量调整(见《服务端环境变量速查》)。
A full space returns 507 quota_exceeded with usedBytes and limitBytes in the error body — "used / limit" is exactly what you need before deleting old versions or raising the quota. All defaults are adjustable through environment variables (see "Server environment variables").
常见问题
FAQ
手机端能编辑,会不会把电脑上的改动覆盖掉?
不会静默覆盖。两端同时改同一处会触发冲突提示:手机端保留你的改动并给出处理出口,电脑端提供差异对比与两个版本的选择。
同步失败提示"配额已满"怎么办?
错误信息里带了用量与上限。要么在服务端调大 NOVARA_SYNC_QUOTA_BYTES,要么减少保留版本数——旧版本会被自动淘汰到上限以内。
The phone can edit — will it overwrite the computer's changes?
Never silently. Editing the same place on both sides triggers a conflict: the phone keeps your edits with exits to resolve, and the computer offers the diff and the two-version choice.
Sync fails with "quota exceeded" — what do I do?
The error carries usage and the limit. Either raise NOVARA_SYNC_QUOTA_BYTES on the server or lower version retention — old versions are pruned automatically to fit.
手机只读访问Read-only mobile access
生成只读令牌
Issue a read-only token
- 打开只读访问桌面端 → 设置 → 互联同步卡片 → 只读访问。
- 点「生成」得到一枚 24 字符令牌,按六组显示:
XXXX-XXXX-XXXX-XXXX-XXXX-XXXX。 - 当场保存明文只显示这一次——服务端只存哈希,关掉弹窗就再也拿不回来。
- Open read-only accessDesktop → Settings → Encrypted sync card → Read-only access.
- Click "Generate"You get a 24-character token, shown in six groups:
XXXX-XXXX-XXXX-XXXX-XXXX-XXXX. - Save it on the spotThe plaintext is shown exactly once — the server stores only a hash; once the dialog closes it is gone for good.
令牌字母表刻意剔除 I、L、O、U(Crockford base32),你抄写时把 1 抄成 I、0 抄成 O 也会被自动折叠纠正。手机输入时小写、带连字符、夹着空格都没关系。
The token alphabet deliberately excludes I, L, O and U (Crockford base32): if you copy 1 as I or 0 as O, input is folded and corrected automatically. On the phone, lowercase, hyphens and stray spaces are all fine.
两个随时可用的开关:重新生成会让旧令牌与旧链接立即失效(按钮文案本身就写着后果);作废立即掐断所有用这枚令牌的会话——手机丢了就点它。
Two always-available switches: regenerate instantly kills the old token and old links (the button's own label states the consequence); revoke immediately cuts every session using the token — the button to press when the phone is lost.
链接长什么样
What the link looks like
https://你的域名/web/#s=<spaceId>- 空间 ID 放在
#片段里:不会发送给服务器,不进服务端日志,也不进 Referer。它是定位符,不是凭据。 - 链接里没有令牌、没有口令。把链接发出去 ≠ 把访问权发出去——打开的人仍要输入令牌与你的解锁密码。
- 链接由桌面端生成并复制,把链接传到手机最省事的方式是发给自己(IM、邮件都行),不必手输长 URL。
- The space id sits in the
#fragment: it is never sent to the server, never lands in server logs, never in Referer. It is a locator, not a credential. - The link carries no token and no passphrase. Sharing the link ≠ sharing access — whoever opens it still needs the token and your lock password.
- The desktop generates and copies the link; the easiest way to move it to the phone is sending it to yourself (any messenger or email) rather than typing a long URL.
手机上打开
Opening it on the phone
- 点开链接进入解锁页,两个输入框:令牌 + 口令。
- 输入令牌就是刚才那枚 24 字符只读令牌(自动规范化)。
- 输入解锁密码是包装空间密钥的那个 Novara 解锁密码——不是手机密码,也不是任何其他密码。
- 浏览四个分区都可浏览,支持搜索与 TOTP 动态码;界面上没有任何编辑、删除、新建入口。
- Tap the linkThe unlock page opens with two fields: token + passphrase.
- Enter the tokenThe 24-character read-only token from before (normalized automatically).
- Enter the unlock passwordThis is the Novara unlock password that wraps the space key — not the phone's password, not anything else.
- BrowseAll four areas are browsable with search and TOTP codes; the interface has no edit, delete or create controls anywhere.
两道凭据缺一不可:令牌只是门禁,解不开任何内容;真正的解密靠你的解锁密码在手机内存里完成。
Both credentials are required: the token is only a door pass and decrypts nothing; the actual decryption happens in phone memory with your unlock password.
为什么必须 HTTPS
Why HTTPS is mandatory
浏览器的加密能力(crypto.subtle)只在安全上下文里提供。用 http:// 打开非回环地址,页面会明确提示"当前浏览器不支持所需的加密能力"——不是白屏,也不是故障。自签证书未被手机信任时一样:点"继续访问"绕不过去,必须安装 CA 并开启完全信任。
The browser's crypto (crypto.subtle) is only available in a secure context. Open a non-loopback address over http:// and the page plainly says "this browser does not support the required encryption capability" — not a blank screen, not a malfunction. Same when a self-signed certificate is not trusted by the phone: tapping "continue anyway" does not get around it; you must install the CA and enable full trust.
服务端自己也把关:非 HTTPS 且非回环的 API 请求一律拒绝,返回 403 与错误原文 https is required for api requests。手机端与服务器两侧对称拒绝明文,凭据没有"悄悄收下"的路径。
The server enforces its own side: API requests that are neither HTTPS nor loopback are refused with 403 and the exact error https is required for api requests. Phone and server reject plaintext symmetrically — there is no path where credentials are "quietly accepted".
如实说明的限制
Limitations, stated honestly
| 限制 | 原因与做法 |
|---|---|
| 刷新就要重新解锁 | 密码与解密后的内容只存在于当前页面内存,不写入手机任何存储(无 localStorage / IndexedDB / Cookie)。这是安全设计 |
| 主屏图标启动提示"链接不完整" | 空间 ID 在链接 # 片段里,而 PWA 的 start_url 无法携带片段——已知限制。从书签或历史记录进入即可 |
| 明文不落手机 | 复制的内容会进系统剪贴板;Novara 侧不做任何持久化 |
| Limitation | Why, and what to do |
|---|---|
| Refreshing requires unlocking again | The password and decrypted content live only in the current page's memory and are never written to any phone storage (no localStorage / IndexedDB / cookies). This is a security design |
| Home-screen icon says "incomplete link" | The space id is in the link's # fragment, and a PWA start_url cannot carry a fragment — a known limitation. Enter from a bookmark or history instead |
| No plaintext lands on the phone | Copied content goes to the system clipboard; Novara performs no persistence of its own |
安全边界Security boundaries
服务器:持有什么,能做什么
The server: what it holds, what it can do
| 项 | 状态 |
|---|---|
| 同步密文容器(blob) | 持有——密文,AES-256-GCM,无法解密 |
| keywrap 记录 | 持有——被你的解锁密码封装的 SpaceKey |
| 设备令牌 / 只读令牌 / enrollment secret | 只持有 SHA-256 |
| SpaceKey、明文数据、库密码、口令 | 永不持有、永不接触 |
| Item | Status |
|---|---|
| Sync ciphertext containers (blobs) | Held — ciphertext, AES-256-GCM, undecryptable |
| Keywrap records | Held — your SpaceKey wrapped with your unlock password |
| Device tokens / read-only tokens / enrollment secrets | SHA-256 only |
| SpaceKey, plaintext data, vault password, passphrases | Never held, never touched |
因此服务器的管理员可以删除密文、造成不可用,但不能读取明文。可用性与机密性在这里是两件事:备份解决前者,密码强度解决后者。
So a server administrator can delete ciphertext and cause unavailability, but cannot read plaintext. Availability and confidentiality are two different things here: backups address the former, password strength the latter.
唯一真正薄弱的地方
The one genuinely weak spot
拿到"keywrap 记录 + 一枚令牌"的人可以离线暴力破解你的解锁密码。封装用了 PBKDF2-SHA256 三百万次迭代(每次约 0.3 秒),这个成本就是门槛——但它是唯一的门槛。
Someone holding "a keywrap record + a token" can brute-force your unlock password offline. The wrapping uses PBKDF2-SHA256 at three million iterations (about 0.3 seconds per try) — that cost is the gate, and it is the only gate.
选一个强密码,比选哪条上线路径都重要。
Choosing a strong password matters more than choosing which TLS path to take.
两组凭据,分开看
Two kinds of credentials, judged separately
- 只读令牌泄漏 → 对方还得有你的密码才能看内容,且只能读。
- 编辑凭据泄漏 → 对方可以覆盖云端的密文(可用性受损),但依然拿不到明文——每条数据的完整性由密钥签名保护,伪造不出你电脑会接受的版本。
- 发现泄漏就作废:只读令牌作废立即生效;编辑凭据可单独撤销对应的 Web 编辑端设备。
- A leaked read-only token → the holder still needs your password to see anything, and can only read.
- A leaked edit credential → the holder can overwrite the cloud's ciphertext (availability damage), but still never sees plaintext — each version's integrity is protected by a keyed MAC, and they cannot forge a version your computer would accept.
- On any leak, revoke: read-only tokens revoke instantly; edit credentials can be revoked by removing that web-editor device.
传输与日志的既有防线
Standing defenses in transport and logs
- 传输走 TLS(反代终止);服务端自己再加一道闸——非 HTTPS 且非回环的 API 请求一律 403,凭据没有"被明文收下"的路径。
- 全部 /api 响应
Cache-Control: no-store;安全响应头(CSP 等)由服务端对每个响应发出,不经反代的路径同样受保护。 - 日志禁令写进安全基线:令牌、凭据、blob 内容永远不进日志;审计只记元数据(谁、何时、什么动作、结果、字节数)。
- 一切秘密比较走常量时间比较;鉴权失败按计数键与窗口限速。
- Transport is TLS (terminated at the proxy); the server adds its own gate — non-HTTPS, non-loopback API requests get 403, so credentials are never "accepted in plaintext".
- All /api responses carry
Cache-Control: no-store; security headers (CSP etc.) are emitted by the server on every response — protected even on paths bypassing the proxy. - The log prohibition is written into the security baseline: tokens, credentials and blob contents never enter logs; audit records metadata only (who, when, what action, result, byte counts).
- Every secret comparison is constant-time; auth failures are rate-limited by counted keys and windows.
应用边界之外
Beyond the app boundary
以下威胁在 Novara 的能力范围之外,诚实说明:
Stated honestly, these threats are outside Novara's reach:
- 已解锁的主机:屏幕录制、键盘记录、恶意浏览器扩展都能看到你正在看的内容——任何本地应用都一样。
- 云端 AI 客户端:你主动授权 MCP 的 Agent 若把读取结果发给其模型服务商,那是该客户端的责任边界;Novara 侧的脱敏与审计仍然生效。
- 部署者责任:HTTPS、服务器补丁、备份策略、域名与公网暴露面的管理,属于运行服务端的人——也就是你。
- An unlocked host: screen recording, keyloggers and malicious browser extensions see what you see — as with any local app.
- Cloud AI clients: if an agent you authorized via MCP sends what it read to its model provider, that is that client's responsibility boundary; Novara's redaction and audit still applied on its side.
- Deployer responsibility: HTTPS, server patching, backup policy, managing the domain and public exposure — belong to whoever runs the server, which is you.
常见问题FAQ
会不会哪天变成收费的云服务?
不会。架构上就没有官方云:服务器是你自己的,Novara 官方既没有你的数据,也没有你的密钥。
服务器挂了/忘续费,我的数据会没吗?
不会。你的电脑是权威副本,全部数据都在本地。服务器丢了只是"暂时不能跨设备访问",重建一个、重新配对、推一份上去就恢复了。
能同时接几台设备?
电脑、Web 编辑端各算一台,数量不受限;每台都能在设备中心单独撤销或重置令牌。
能给家人/朋友看吗?
可以:把只读令牌和链接给对方(不要把解锁密码一起给——那样等于交出全部数据)。更好的做法是用安全快照导出只读副本单独分享。
手机上能编辑吗?
能。用「编辑访问」生成编辑凭据后,手机上可改备忘、待办、便签与 Markdown 文档(富文本日记在 Web 端只读)。
为什么我的手机上看不到回收站里的内容?
这是设计:已删除(在回收站里)的数据不会出现在手机端。
Will this become a paid cloud service one day?
No. There is no official cloud in the architecture: the server is yours, and Novara holds neither your data nor your keys.
If the server dies or I forget to renew it, is my data gone?
No. Your computer is the authoritative copy — all data is local. Losing the server only pauses cross-device access; rebuild one, re-pair and push a copy up to be fully restored.
How many devices can connect?
Computers and the web editor each count as one; no count limit; each can be revoked or have its token reset individually in the device center.
Can I show it to family or friends?
Yes: hand them the read-only token and the link (never the unlock password — that would hand over all of the data). Even better, export a snapshot as a separate read-only copy to share.
Can I edit from the phone?
Yes. After generating edit credentials via "edit access", the phone can edit memos, to-dos, notes and Markdown documents (rich-text journals are read-only on the web).
Why can't the phone see trash contents?
That is design: deleted (trashed) data never appears on the phone.
继续阅读Keep reading
- No server deployed yet → the sync deployment guide (Windows / Docker / NAS / VPS, every path)
- Just want to "look something up" → the secure snapshot guide is simpler