mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-09 03:20:56 +00:00
`setup_register` in `web_auth.rs` used to round-trip the user's settings file through `toml::Value` + `toml::to_string_pretty`, which strips every comment, blank line, and explicit key ordering on the way out. A user who'd hand-commented their `~/.fabro/settings.toml` would see all of that lost on the next GitHub App registration. Switches the edit path to `toml_edit::DocumentMut`, which preserves prefix decoration (comments, blank lines) on every key. Adds `toml_edit = "0.22"` as a workspace dependency (already pulled in transitively via `toml 0.8`) and declares it in `fabro-server`. Implementation notes: - New `ensure_nested_table(doc, &["server", "web"])` walks a dotted path and `or_insert`s missing intermediate tables without touching existing ones. - New `set_preserving_decor(table, key, value)` replaces an entry's value while copying the old key's `leaf_decor` forward. Without that workaround, `toml_edit::Table::insert` drops the prefix decoration of the replaced key -- which would strip a top-of-file comment attached to `_version = 1` or any other value we update. - `_version` is only inserted when missing; it's always `1` today, so rewriting it every time is unnecessary and would trample its decor. - `merge_settings_keys` now takes `&mut toml_edit::DocumentMut` instead of `&mut toml::Value`. The flow in `setup_register` parses the file on disk into a `DocumentMut`, applies the merge, and writes `doc.to_string()` back. Adds a new test `merge_settings_keys_preserves_comments_and_unrelated_keys` that round-trips a fixture file containing: - A top-of-file comment attached to `_version` - A comment above `[server.storage]` - A comment above a pre-existing `[server.integrations.slack]` table - Unrelated keys in `[server.storage]`, `[server.integrations.slack]`, and `[run.model]` and asserts that every comment and every unrelated key survives the merge, that the new GitHub App keys are present, and that the final output still parses as a valid v2 `SettingsFile` via `fabro_config::ConfigLayer::parse`. Also strengthens the existing `merge_settings_keys_writes_v2_server_integrations_github` test with a round-trip parse of the emitted TOML through `ConfigLayer::parse` to ensure the output is real v2 config, not just a JSON-shaped blob. 3,765 workspace tests pass (+1 new). `cargo fmt --check --all` and `cargo clippy --workspace -- -D warnings` are clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
85 lines
2.4 KiB
TOML
85 lines
2.4 KiB
TOML
[package]
|
|
name = "fabro-server"
|
|
edition.workspace = true
|
|
version.workspace = true
|
|
publish = false
|
|
license.workspace = true
|
|
description = "HTTP server for Fabro pipelines"
|
|
|
|
[lib]
|
|
doctest = false
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[dependencies]
|
|
fabro-spa = { path = "../fabro-spa" }
|
|
fabro-config = { path = "../fabro-config" }
|
|
fabro-graphviz = { path = "../fabro-graphviz" }
|
|
fabro-hooks = { path = "../fabro-hooks" }
|
|
fabro-interview = { path = "../fabro-interview" }
|
|
fabro-slack = { path = "../fabro-slack" }
|
|
fabro-workflow = { path = "../fabro-workflow" }
|
|
fabro-validate = { path = "../fabro-validate" }
|
|
fabro-sandbox = { path = "../fabro-sandbox", features = ["daytona"] }
|
|
fabro-github = { path = "../fabro-github" }
|
|
fabro-agent = { path = "../fabro-agent" }
|
|
fabro-llm = { path = "../fabro-llm" }
|
|
fabro-model = { path = "../fabro-model" }
|
|
fabro-proc = { path = "../fabro-proc" }
|
|
fabro-retro = { path = "../fabro-retro" }
|
|
fabro-types = { path = "../fabro-types" }
|
|
fabro-util = { path = "../fabro-util" }
|
|
fabro-api = { path = "../fabro-api" }
|
|
fabro-store = { path = "../fabro-store" }
|
|
chrono.workspace = true
|
|
futures-util.workspace = true
|
|
axum.workspace = true
|
|
axum-extra.workspace = true
|
|
cookie.workspace = true
|
|
dirs.workspace = true
|
|
tower = "0.5"
|
|
tower-http = { version = "0.6", features = ["trace"] }
|
|
tokio-stream = { workspace = true, features = ["sync"] }
|
|
base64.workspace = true
|
|
jsonwebtoken.workspace = true
|
|
tokio.workspace = true
|
|
tokio-rustls = "0.26"
|
|
rustls = { version = "0.23", default-features = false, features = ["std", "ring"] }
|
|
rustls-pemfile = "2"
|
|
rustls-pki-types = "1"
|
|
hyper = "1"
|
|
hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1", "http2"] }
|
|
tower-service = "0.3"
|
|
x509-parser = "0.16"
|
|
serde.workspace = true
|
|
serde_json.workspace = true
|
|
serde_yaml = "0.9"
|
|
anyhow.workspace = true
|
|
clap.workspace = true
|
|
toml.workspace = true
|
|
toml_edit.workspace = true
|
|
tracing.workspace = true
|
|
ulid.workspace = true
|
|
uuid.workspace = true
|
|
hmac.workspace = true
|
|
sha2.workspace = true
|
|
hex.workspace = true
|
|
reqwest.workspace = true
|
|
rand.workspace = true
|
|
bytes = "1"
|
|
tempfile = "3"
|
|
object_store.workspace = true
|
|
mime_guess.workspace = true
|
|
regex.workspace = true
|
|
semver.workspace = true
|
|
walkdir.workspace = true
|
|
multer = "3"
|
|
|
|
[dev-dependencies]
|
|
tokio = { workspace = true, features = ["test-util", "macros"] }
|
|
tower = "0.5"
|
|
http-body-util = "0.1"
|
|
openapiv3 = "2"
|
|
serde_yaml = "0.9"
|
|
fabro-sandbox = { path = "../fabro-sandbox" }
|