config-kit¶
The tool-chest component config system, in one standard-library-only package (toolchest_config). A component
declares its settings once; this kit validates them, layers them, writes the private file atomically, and serves the
command-line contract the dashboard's Settings page uses. The research component is the first consumer
(research/src/research/settings.py).
The model¶
| Layer (later wins) | Where | Written by |
|---|---|---|
| defaults | the component's schema | the component's code |
| shared | tracked tool-chest.toml, under [<component>] ([<component>.limits], ...) |
people, in a commit; never the UI |
| private | <data_root>/config/<component>.toml, mode 0600 |
the dashboard or <component> config set |
| environment | variables the schema maps to keys | whoever starts the process |
Every private file has the same envelope:
schema = 1
component = "research"
[limits]
papers_per_run = 20
[block.arxiv] # a block has a `kind`, which selects its own set of fields
kind = "arxiv-api"
api_url = "https://export.arxiv.org/api/query"
A value that fails validation is reported and ignored (the next layer down is used). An invalid environment variable stops the process: it was started wrongly, so it does not run on a silent fallback.
Secrets are references¶
A field of type secret_ref holds keychain:<service>, never a value. A value typed there is refused and not echoed.
A reference is resolved at the moment of use with toolchest_config.secrets.resolve(ref, fetch); a missing item fails
closed. The UI shows the reference and whether the item is present, and the Terminal command that stores it (it
prompts for the value, so none is on the command line). Entering secrets in the browser is v2.
Adding a component¶
- Declare a
Schema(fields, block kinds, built-in blocks, environment variables). Defaults must equal the values the component uses today; pin them to the code constants with a test. - Expose the contract from the component's CLI:
from toolchest_config import contract
sys.exit(contract.main(SCHEMA, ["get"], data_root=root, tracked_path=tracked,
secret_state=secrets.keychain_state))
<command> --data-root <root> schema | get | set | validate. set reads {"changes": {"<key>": <value>}} on
stdin (a null removes a key), validates the whole result, and writes nothing if anything is wrong.
3. Read effective values with schema.resolve(...) (see settings.effective() in research), never the file directly.
4. Register the command in tool-chest.toml:
The dashboard imports no component; it runs that command (no shell, bounded time) and reads JSON.
Tests¶
python3 -m unittest discover -s config-kit/tests -t config-kit/tests (also run by make check).