# 0022: Settings are layered, and every field says who may write it Status: accepted; the crate and the pane are live, file loading is not. Everything Lumbridge could be configured by was an environment variable set inside `scripts/open-metal-lumbridge.sh`: invisible from inside the application, and unchangeable without editing the launcher. ## Layers Compiled default → `settings.toml` → environment. The environment sits **above** the file, which is the reverse of the usual arrangement and is deliberate. Decision 0016 calls `LUMBRIDGE_CLAUDE_OAUTH=0` "one switch off". A switch that a configuration file can silently re-enable is not a switch, so the file loses. A value pinned by the environment renders **disabled**, naming the variable that pinned it. Not annotated — disabled. An interface that accepts an edit which will not take effect has lied about what it does. Every value carries where it came from, for the same reason a usage number carries a provenance: a value you cannot trace is a value you cannot trust. ## Write authority Routing every write through the `Configure` capability is the obvious design and it is wrong. It would hand a layout-only agent a way to set the program that every future pane launches, which is precisely the guarantee decision 0006 exists to make. So each field carries a `WriteAuthority`. Anything naming a **program, a path, or a network destination** is `Human`, and a non-human origin is refused rather than quietly downgraded. A test asserts the rule from the path itself, so a new setting whose name contains `path` or `feed` cannot ship as agent-writable. ## What is not a setting, permanently `FORBIDDEN_PATHS` names them, with the reason beside each, and a test asserts they never appear: - **`usage.oauth_endpoint`** — the URL an access token is sent to. A configuration file that can redirect it is a credential exfiltration path with a friendly name. - **`usage.credentials_path`** — the file the token is read from; the same attack from the other end. - **`usage.client_name`** — the identity Lumbridge presents. Decision 0016 refuses to send the harness's own User-Agent because it would make our traffic indistinguishable from the harness's in the provider's logs; a settings key would undo that. - **`terminal.shell_program`** — decision 0006 again. ## Unknown keys are ignored, not rejected, and not silent A file written by a newer build must still open in an older one, so the schema does not deny unknown fields. But a key that vanished without a word is a key the user thinks is in effect, so they are collected and reported on the Advanced page. A parse *error* is an error: the last good content is kept and a banner shown, because a typo must never silently reset a configuration to defaults. ## Advanced states facts, not toggles "What Lumbridge reads" lists every file, endpoint and child process by name, and ends with "Nothing is sent anywhere else. There is no telemetry to turn off." That is a fact. Rendering it as a switch nobody can flip would be theatre. ## Paths `~/.config/lumbridge/settings.toml` on Linux; on macOS under `Application Support` and explicitly **not** `~/Library/Preferences`, which is CFPreferences territory where `defaults` and the preference daemon rewrite files in their own format — fatal for a file whose comments are its documentation. Behind a trait with a shared contract test, so the macOS half is at least checked on Linux. ## Not in this pass The file is not read yet: the pane resolves compiled defaults against the real environment, which is why the environment-pinned rows are already correct. Load, atomic 0600 write through `toml_edit` to preserve comments, and a directory watcher with echo suppression are the next step — a debounced write that bounces off its own watcher event loops forever, so the hash of the last written bytes has to be recorded and matched. Editable controls are also pending. Every row shows its value, origin, authority and when it applies; none of them can yet be clicked. That is the honest order: the pane tells the truth about the configuration before it offers to change it.