Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ categories = ["network-programming", "web-programming::http-server"]

# δΊŒθΏ›εˆΆθ΅° CalVer,crate θ΅° SemVer β€”β€” δΈ€θ€…ζ˜―δΈ€ε›žδΊ‹οΌŒε–η»™δΈεŒηš„δΊΊγ€‚
# θΏ™ι‡Œζ˜― crate ηš„η‰ˆζœ¬γ€‚
version = "0.60.0"
version = "0.61.0"

[workspace.dependencies]
# ── 内部 crate ───────────────────────────────────────────
Expand Down
24 changes: 24 additions & 0 deletions release-notes/0.61.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
This release makes safe mode work for the case it exists for: a configuration that does not load. Core serves the control plane anyway, says which line is wrong, and can repair the two commonest mistakes in one step. Before, a safe-mode core exited on the same error as a normal start, and the desktop app could only say that core had stopped.

**Upgrade notes**

- The control-plane protocol version (`CONTROL_API_VERSION`) goes from 36 to 37. ThinkWatch Lite connects only to a core with the same protocol version. ThinkWatch Lite 2026.10.2 includes 0.60.0 (protocol 36) and does not connect to 0.61.0. A server used with it stays on 0.60.0 until the app is updated to a release that includes 0.61.0; `sudo twcore upgrade --version 0.60.0 --restart` switches a server back.
- The request store's schema is unchanged (25): upgrading from 0.60.0 keeps the request history.
- The configuration format is unchanged.
- Changed in the protocol:
- New: `GET /config/repair` (`ConfigRepairPlan` β†’ `ConfigRepair`: `base_version` and a list of `ConfigFix`) and `POST /config/repair` (`RepairConfig`: `ConfigRepairRequest { base_version }` β†’ `ConfigWritten`). A web view may call both.
- `ConfigFix` has `kind` (`unknown_value` or `unknown_field`), `field` (a path such as `providers[0].protocol`), `line`, `value` (masked) and `now` (the default the field goes back to, when it is a single value).
- In safe mode, `Status.config_rejected` is set from the start when the configuration does not load, and `Status.gateway_addr` is null as before.
- Message codes, compared with 0.60.0:
- New: `config.unknown_variant` (`field`, `value`, `expected`), `config.unknown_field` (`field`, `expected`) and `control.config_not_repairable`.
- A value outside its choices and an unknown field used to come as `config.unparsable` with serde's sentence in `detail`; they now use the two new codes. Other parse errors still use `config.unparsable`.

**Safe mode with a configuration that does not load.** `twcore serve --safe` used to load the configuration before anything else and exit when it did not load. It now serves the control plane with a stand-in configuration: the control key comes from the file, so a client that reads it from the same file can connect, and everything else is a default. The data plane does not start.
- `Status.config_rejected` says from the start which line is wrong, in the same form as for an edit that was refused while running: the stage, the message, the line and the line itself with secrets masked.
- Saving a configuration that loads (through the control plane, a rollback, a repair, or by editing the file) swaps it in as usual. A client then restarts core in normal mode.
- A file in which the control key cannot be found, such as one that is not valid YAML, still makes `serve --safe` exit, since nobody could connect to the control plane.

**One-click repair.** `GET /config/repair` lists what a repair would change, and `POST /config/repair` makes those changes and writes the file.
- Only two kinds of mistake are repaired, and each repair removes one key. A value outside its choices, such as `titling: passthrough`, goes back to the field's default. An unknown field, such as a misspelled name, is removed. A section left empty is removed with its last key. Comments, layout and every other key are kept.
- A repair is offered only when the repaired configuration loads. A syntax error, a missing field and an error in the configuration as a whole (such as two upstreams with the same name) are left to the user.
- The repair is computed again from the file on disk when it is applied, and refused with 409 when the file has changed since the plan. It goes through the same path as any other write, so the previous version is in the history and can be rolled back.
Loading