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
51 changes: 44 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,17 @@ These are deliberate design decisions, not oversights. Do not "improve" them wit
`late_command` or a chroot script, where one `curl` is writable and composing
Proxmox's JSON is not.
- `src/config.rs` — environment configuration. `Config::from_lookup` takes a lookup closure so
tests never touch the process environment.
tests never touch the process environment — which is also the seam every configuration
file hangs off: a file is just another source behind that closure.
- `src/tomlconfig.rs` — the optional **TOML** file `RESCRIPTUM_CONFIG` names, for the
platform where a person edits configuration by hand. It **maps a document onto the same
`RESCRIPTUM_*` names and does nothing else**, so one place still decides what a setting
means and the file cannot grow behaviour the environment lacks. `MAPPING` is that table,
and a unit test asserts it covers `envfile::KNOWN_KEYS` exactly — a setting missing from
it is one the file silently cannot configure. Writes go through `toml_edit`, which edits
the document in place: **replace the value, never the entry**, because a setting's
explanation lives in the *key's* decor and inserting over the key throws the paragraph
away.
- `src/envfile.rs` — the optional file of defaults `RESCRIPTUM_ENV_FILE` names, and the
writer behind `config set`: `rewrite()` edits lines where they stand, **uncommenting** a
commented setting rather than appending a duplicate, because on a packaged install those
Expand Down Expand Up @@ -401,9 +411,16 @@ spend into an apparent 293% overrun.**

| Build | Bytes |
|---|---|
| `sqlite` + `boot` (default) | 2,741,360 |
| `sqlite` only | 2,482,000 |
| neither | 1,316,648 |
| `sqlite` + `boot` (default) | 2,813,712 |
| `sqlite` only | 2,557,592 |
| `boot` only | 1,649,048 |
| neither | 1,392,544 |

Re-measured 2026-08-29 on armv7-gnueabihf (floor 2.17), all four in one sitting. **Both
tables that held these numbers were stale by roughly 200 KB** — this one and
`docs/guide/reference/configuration`, which disagreed with each other as well.
`boot` costs **1,164,120** against `sqlite` alone by this measurement; the budget question
below is written against the older figure and needs re-deciding against this one.

**`boot` costs 259,360 bytes, against a ≤170 KB budget the plan set before any of it was
written** — the image-source catalogue added 31,520 of that. That is recorded in `plans/boot-media.md` with a per-phase breakdown rather
Expand Down Expand Up @@ -745,11 +762,14 @@ file or failure). When a PXE install won't start, this is the only diagnostic av

## Configuration

Environment variables only — plus an optional file to read some of them from:
Environment variables — plus an optional file to read them from, in either of two shapes.
Both files set the same variables under the same rules; **the environment wins over both,
and the TOML file wins over the env file**:

| Variable | Default | Role |
|---|---|---|
| `RESCRIPTUM_ENV_FILE` | unset | A file of the same variables. See below |
| `RESCRIPTUM_CONFIG` | unset | A **TOML** file of the same settings, under readable names. See below |
| `RESCRIPTUM_ENV_FILE` | unset | A `KEY=value` file of the same variables. See below |
| `RESCRIPTUM_STORE` | `files` | `files` or `sqlite` |
| `RESCRIPTUM_ANSWERS_DIR` | `/srv/answers` | Directory of answer documents |
| `RESCRIPTUM_DB_PATH` | `/srv/answers.db` | SQLite database, when `RESCRIPTUM_STORE=sqlite` |
Expand Down Expand Up @@ -803,6 +823,23 @@ It is not a shell: no `${}` expansion, no inline comments (a `#` in a value is p
value — truncating a token silently is worse than a comment landing in a value, where it is
loud), `export` accepted so one file can also be sourced, a duplicate key is an error.

**`RESCRIPTUM_CONFIG` (`src/tomlconfig.rs`)** is the same job in the shape a person reads:
the prefix goes away and tables do the grouping (`store.kind`, `admin.token`,
`server.workers`). It exists because 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. Every rule above carries over unchanged, and three things are specific to it:

- **It 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%.
- **`""` is unset**, the same rule an exported-but-empty variable has — which is what lets
`config unset` empty a line instead of deleting the paragraph documenting it. A list or a
table where a value belongs is a startup *error*, unlike a misspelled key, which warns:
it was aimed at a real setting, so serving the default would be the silent failure.
- **A configuration file must not live in the answers directory.** Every servable `.toml`
at the top of that directory is an answer document, and this format shares the extension
— `check` reports one dropped there as a misplaced answer and `migrate` offers to move
it. A test pins that rather than leaving it to be discovered.

## Commands

Local development (once the crate exists):
Expand Down Expand Up @@ -880,7 +917,7 @@ is the procedure*), which `AGENTS.md` also points at.

## Testing expectations

582 tests, plus the package's own harnesses (see *The DSM package*, and note that
613 tests, plus the package's own harnesses (see *The DSM package*, and note that
`cargo test` does not run those). `docs/development/testing.md` has the per-suite table;
the rules that decide where a test goes:

Expand Down
26 changes: 18 additions & 8 deletions docs/guide/reference/cli.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ Sans argument, `rescriptum` lance le serveur. Tout le reste est une sous-command
| `rescriptum config` | afficher la configuration, et d'où vient chaque valeur |
| `rescriptum config --json` | la même chose, pour un panneau de réglages |
| `rescriptum config --value CLÉ` | une valeur, pour un script — jamais un identifiant |
| `rescriptum config set C=V …` | éditer le fichier que `RESCRIPTUM_ENV_FILE` nomme |
| `rescriptum config unset CLÉ …` | recommenter un réglage dedans |
| `rescriptum config set C=V …` | éditer le fichier que `RESCRIPTUM_CONFIG` ou `RESCRIPTUM_ENV_FILE` nomme |
| `rescriptum config unset CLÉ …` | y retirer un réglage |
| `rescriptum --help` | usage et variables d'environnement |

Toutes lisent les mêmes [variables d'environnement](./configuration.md), dont
[`RESCRIPTUM_ENV_FILE`](./configuration.md#le-fichier-denvironnement) — résolu en premier,
[`RESCRIPTUM_CONFIG`](./configuration.md#le-fichier-toml) et
[`RESCRIPTUM_ENV_FILE`](./configuration.md#le-fichier-denvironnement) — résolus en premier,
donc un fichier illisible arrête toute commande ayant besoin de la configuration. `--help`
et `--version` répondent avant sa lecture, parce que ce sont les commandes qu'on lance
quand quelque chose ne va pas. Il n'y a pas d'options globales.
Expand Down Expand Up @@ -124,10 +125,16 @@ env file: /var/packages/rescriptum/etc/rescriptum.env
RESCRIPTUM_ADMIN_TOKEN (set) file
```

La troisième colonne est l'essentiel. Le fichier fournit des **valeurs par défaut** et
l'environnement réel l'emporte : une valeur marquée `environment` ne peut donc pas être
changée en éditant le fichier — et `config set` le dit, plutôt que de vous laisser écrire
quelque chose que le serveur en cours continuera d'ignorer.
La troisième colonne est l'essentiel. Les fichiers fournissent des **valeurs par défaut**
et l'environnement réel l'emporte : une valeur marquée `environment` ne peut donc pas être
changée en éditant un fichier — et `config set` le dit, plutôt que de vous laisser écrire
quelque chose que le serveur en cours continuera d'ignorer. Avec un fichier TOML la colonne
affiche `toml file`, et nommer les deux fichiers affiche les deux chemins ainsi que l'ordre
dans lequel ils l'emportent.

**`config set` écrit dans le fichier TOML quand les deux sont nommés**, parce que c'est
celui que le serveur lit en premier : écrire l'autre serait une modification qui ne change
rien en silence.

**Un identifiant n'est jamais affiché**, sous aucune forme de cette commande. Un jeton
apparaît comme `(set)` ou `(not set)` ; `--value` refuse tout net.
Expand All @@ -140,7 +147,10 @@ wrote /var/packages/rescriptum/etc/rescriptum.env
L'écriture laisse le fichier tel qu'il est par ailleurs : les commentaires restent, un
réglage est remplacé là où il se trouve, et un réglage commenté est **décommenté sur place**
plutôt qu'ajouté en dessous — ce qui compte quand le commentaire au-dessus est la seule
documentation qu'a le fichier.
documentation qu'a le fichier. Dans un fichier TOML, le même soin s'applique au document :
la valeur est remplacée là où elle est, son commentaire de fin de ligne survit, et `config
unset` **vide la valeur au lieu de supprimer la ligne**, pour que le paragraphe qui
explique le réglage reste en place.

Deux refus sont délibérés :

Expand Down
23 changes: 16 additions & 7 deletions docs/guide/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ With no arguments, `rescriptum` runs the server. Everything else is a subcommand
| `rescriptum config` | show the configuration, and where each value comes from |
| `rescriptum config --json` | the same, for a settings panel |
| `rescriptum config --value KEY` | one value, for a script — never a credential |
| `rescriptum config set K=V …` | edit the file `RESCRIPTUM_ENV_FILE` names |
| `rescriptum config unset KEY …` | comment a setting back out of it |
| `rescriptum config set K=V …` | edit the file `RESCRIPTUM_CONFIG` or `RESCRIPTUM_ENV_FILE` names |
| `rescriptum config unset KEY …` | take a setting back out of it |
| `rescriptum --help` | usage and the environment variables |

All of them read the same [environment variables](./configuration.md), including
[`RESCRIPTUM_ENV_FILE`](./configuration.md#the-env-file) — which is resolved first, so a
[`RESCRIPTUM_CONFIG`](./configuration.md#the-toml-file) and
[`RESCRIPTUM_ENV_FILE`](./configuration.md#the-env-file) — which are resolved first, so a
file that cannot be read stops any command that needs configuration. `--help` and
`--version` are answered before it is read, because they are what you reach for when
something is wrong. There are no global flags.
Expand Down Expand Up @@ -123,9 +124,14 @@ env file: /var/packages/rescriptum/etc/rescriptum.env
RESCRIPTUM_ADMIN_TOKEN (set) file
```

The third column is the point. The file supplies **defaults** and the real environment
wins, so a value marked `environment` cannot be changed by editing the file — and `config
set` says so rather than letting you write something the running server will ignore.
The third column is the point. The files supply **defaults** and the real environment
wins, so a value marked `environment` cannot be changed by editing a file — and `config
set` says so rather than letting you write something the running server will ignore. With
a TOML file the column reads `toml file`, and naming both files prints both paths plus the
order they win in.

**`config set` writes the TOML file when both are named**, because it is the one the server
reads first: writing the other would be a change that silently does nothing.

**A credential is never printed**, by any form of this command. A token shows as `(set)` or
`(not set)`; `--value` refuses outright.
Expand All @@ -137,7 +143,10 @@ wrote /var/packages/rescriptum/etc/rescriptum.env

Writing keeps the file as it is otherwise: comments stay, a setting is replaced where it
stands, and one that is commented out is **uncommented in place** rather than appended
below — which matters when the comment above it is the only documentation the file has.
below — which matters when the comment above it is the only documentation the file has. In
a TOML file the same care applies to the document: the value is replaced where it stands,
its trailing comment survives, and `config unset` **empties the value rather than deleting
the line**, so the paragraph explaining the setting stays where it was.

Two refusals are deliberate:

Expand Down
Loading
Loading