feat(config): a TOML configuration file, for where a person edits it by hand - #3
Merged
Conversation
…by hand `RESCRIPTUM_CONFIG` names a file that sets the same settings under readable names: the prefix gone, tables doing the grouping (`store.kind`, `admin.token`, `server.workers`). It exists for the platform the project was written for — on DSM there is no environment, there is a file, and `RESCRIPTUM_ANSWERS_DIR=…` on every line is a poor thing to hand somebody editing in File Station. `src/tomlconfig.rs` maps a document onto the `RESCRIPTUM_*` names and does nothing else: every value reaches `Config::from_lookup` under the key it would have had in the environment, so one place still decides what a setting means and this format cannot grow behaviour the environment lacks. A unit test asserts `MAPPING` covers `envfile::KNOWN_KEYS` exactly — a setting missing from it is one the file silently cannot configure. Every rule the env file has carries over unchanged: named and never discovered, the real environment wins, and a file that was asked for and cannot be read is a startup error. Naming both files is a transition rather than a steady state, so nothing is refused and the order is said out loud: the environment beats the TOML file, which beats the env file. `config set` writes the TOML file when both are named, because writing the other would be a change that silently does nothing. Three things the implementation settled: - **Replace the value, never the entry.** A setting's explanation lives in the *key's* decor, so inserting over an existing key throws away the paragraph above it — which on a packaged install is the only documentation the configuration has. - **`unset` empties the value rather than deleting the line**, for the same reason. Empty already counts as unset everywhere else in this program. - **A configuration file must not live in the answers directory.** Every servable `.toml` at the top of it is an answer document and this format shares the extension, so `check` reports one dropped there as a misplaced answer. Found by writing the tests, and pinned by one rather than left to be discovered. Costs a mapping, not a dependency: `toml_edit` already parses every answer document. Measured on armv7, +14,544 bytes (2,799,168 → 2,813,712), 0.5%. While measuring: both size tables in the repository were stale by roughly 200 KB and disagreed with each other. All four feature combinations re-measured in one sitting and both tables corrected; the `boot` budget question is now written against a figure that is 1,164,120 rather than the older one. Not in this commit, deliberately: the DSM package still writes its `.env`. Switching it means a `postupgrade` that translates the old file once, and `packaging/dsm/CLAUDE.md` requires that to be watched running on the machine. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KQnAk5r4fLKcWuAwUY6Pa6
wamxx
added a commit
that referenced
this pull request
Aug 30, 2026
Since v0.2.0: the whole boot chain and a directory per identity (#2), a TOML configuration file (#3), and four defects that were live in shipped code — a rollback blind over the file store, a write that could widen the permissions of a document holding a root password hash, a log target that stopped every CLI command for anyone but the service user, and a group `.ipxe` that arms machines nothing can disarm. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KQnAk5r4fLKcWuAwUY6Pa6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RESCRIPTUM_CONFIGnames a file that sets the same settings under readable names — the prefix gone, tables doing the grouping. It exists for the platform this project was written for: on DSM there is no environment, there is a file, andRESCRIPTUM_ANSWERS_DIR=…on every line is a poor thing to hand somebody editing in File Station.The shape of it
src/tomlconfig.rsmaps a document onto theRESCRIPTUM_*names and does nothing else. Every value reachesConfig::from_lookupunder the key it would have had in the environment, so one place still decides what a setting means and this format cannot grow behaviour the environment lacks — which is what keeps two configuration files from becoming two configurations. A unit test assertsMAPPINGcoversenvfile::KNOWN_KEYSexactly: a setting missing from it is one the file silently cannot configure.Every rule the env file has carries over unchanged — named and never discovered, the real environment wins, an unreadable named file is a startup error. Naming both files is a transition rather than a steady state, so nothing is refused and the order is said out loud at startup: the environment beats the TOML file, which beats the env file.
config setwrites the TOML file when both are named, because writing the other would be a change that silently does nothing.What the implementation settled
unsetempties the value rather than deleting the line, for the same reason. Empty already counts as unset everywhere else here..tomlat the top of it is an answer document and this format shares the extension, socheckreports one dropped there as a misplaced answer. Found by writing the tests; pinned by one rather than left to be discovered.Cost
A mapping, not a dependency —
toml_editalready parses every answer document. Measured on armv7: +14,544 bytes (2,799,168 → 2,813,712), 0.5%.While measuring, both size tables in the repository turned out to be stale by roughly 200 KB and to disagree with each other. All four feature combinations were re-measured in one sitting and both tables corrected. The
bootbudget question is now written against 1,164,120 rather than the older figure, and says so.Tests
613 (+31), including the two that were watched failing before being trusted: the precedence between the two files, and the comments surviving a write.
Not in this PR, deliberately
The DSM package still writes its
.env. Switching it means apostupgradethat translates the old file once, andpackaging/dsm/CLAUDE.mdrequires that to be watched running on the machine rather than reasoned about at a desk.🤖 Generated with Claude Code
https://claude.ai/code/session_01KQnAk5r4fLKcWuAwUY6Pa6