From bca19b6eb571591551fafa64bd7c7807c72dac59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20M=C3=A9ndez?= Date: Mon, 28 Sep 2026 03:03:49 +0000 Subject: [PATCH 1/3] docs: decision 0015, operator facing commands carry the Keel name The Keel name becomes the real command and the turnkey-* name is kept as a symlink to it, both working, as a general policy rather than a per-appliance choice. Compatibility with TurnKey is a stated property of this project (0008), so an operator who pasted a command out of TurnKey's documentation, or who wrote a script against turnkey-wp last year, must not silently lose it. The note says which of tracker#12's commands the policy moves now and which wait, and corrects two things in that table. turnkey-php and turnkey-mysql-install-perf-info-schemas are called inherited there; they are ordinary files in the common repository of this organization, reaching the image through COMMON_OVERLAYS, so the policy applies to them in full and what makes them wait is the rebuild of the whole chain, not ownership. And turnkey-sysinfo ships turnkey-detect-virt as well, which the table missed. A turnkey-* name owned by a Debian package is out of scope here. It is settled by owning the package: the maintainer decided on 2026-09-28 to build keel-version and keel-sysinfo as Keel's own source packages rather than wrap or divert TurnKey's, which is tracker#13. The pair is a closed set, which is what makes that possible: turnkey-sysinfo 1.1.0 has no reverse dependencies and turnkey-version 1.1.3's only one is turnkey-sysinfo. The note also records which symlink mechanism was verified and how. The link is committed into the overlay, because fab-apply-overlay is cp -TdR and -d keeps a link a link, and that was checked by making the copy and running the copied command rather than by reading the flag. --- docs/decisions/0015-operator-command-names.md | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/decisions/0015-operator-command-names.md diff --git a/docs/decisions/0015-operator-command-names.md b/docs/decisions/0015-operator-command-names.md new file mode 100644 index 0000000..a362693 --- /dev/null +++ b/docs/decisions/0015-operator-command-names.md @@ -0,0 +1,165 @@ +# 0015: Operator facing commands carry the Keel name, with the turnkey name kept + +Date: 2026-09-28 +Status: decided by the maintainer + +## Decision + +A command an operator types on a Keel appliance carries this project's name. +Where such a command already exists under a `turnkey-*` name: + +- the **Keel name is the real command** — the file with the code in it; +- the **`turnkey-*` name is kept, as a symlink to it**; +- **both keep working**, and neither is documented as deprecated. + +This is a general policy, not a per-appliance choice. It applies to every +operator facing command a repository of this organization **writes and names +itself**: a file in an appliance overlay, a file in the `common` overlays, a +script installed by a package this project builds. It does not apply to a +command that only exists because some other project's package put it there; +that case is settled below. + +The reason for keeping the old name is the same reason `/etc/turnkey_version` +keeps its name in 0014. Compatibility with TurnKey appliances is a stated +property of this project (0008: the fork is kept upstream-compatible on +purpose). An operator who pasted a command out of TurnKey's documentation, or +who wrote a script against `turnkey-wp` last year, must not silently lose it, +and a rename with no link is exactly that loss — it fails at the moment the +operator needs the command, with `command not found` and no hint of a new +name. + +## What a `turnkey-*` name owned by a Debian package does instead + +Nothing in this note. `turnkey-sysinfo` and `turnkey-version` are shipped by +the Debian packages of the same name, and a dpkg-owned file cannot simply +become a symlink: the next upgrade of the package restores the file, and in +the meantime dpkg either reports the divergence or replaces the link without +asking. A wrapper alongside and a dpkg diversion were both on the table. + +Neither is needed, because the maintainer decided on 2026-09-28 to **build and +own `keel-version` and `keel-sysinfo` as Keel's own Debian source packages** +rather than wrap or divert TurnKey's. A command in a package this project +builds is a command this project names, so the rule above applies to it +directly and there is no dpkg-owned case left to handle. That work is +Keel-Linux/tracker#13 and is not part of this note. + +What makes owning the packages possible is that the pair is a closed set, +measured on the `wordpress-demo` container on 2026-09-28: `turnkey-sysinfo` +1.1.0 has **no reverse dependencies at all**, and the only reverse dependency +of `turnkey-version` 1.1.3 is `turnkey-sysinfo`. Nothing else in the archive +depends on either, so replacing them breaks nothing that we would then have to +go and fix. + +One correction to the inventory that raised this, Keel-Linux/tracker#12: +`turnkey-sysinfo` ships **two** commands, not one. Its dpkg file list on the +build host is `/usr/bin/turnkey-sysinfo`, `/usr/bin/turnkey-detect-virt`, the +`libsysinfo` Python package it imports and the motd fragment under +`/usr/share/turnkey-sysinfo/contrib`. `turnkey-detect-virt` was missed, so the +table's five commands are really six. tracker#13 has to cover both names and +the library, because replacing only `turnkey-sysinfo` leaves a `keel-sysinfo` +calling a `turnkey-detect-virt` nobody owns. + +## Which commands this changes now, and which wait + +The five rows of tracker#12, re-measured: + +| Command | Where it really comes from | When | +| --- | --- | --- | +| `/usr/local/bin/turnkey-wp` | `keel-wordpress`, `overlay/usr/local/bin` | **now** | +| `/usr/local/sbin/turnkey-wordpress-update` | `keel-wordpress`, `overlay/usr/local/sbin` | **now** | +| `/usr/local/bin/turnkey-php` | `common`, `overlays/php/usr/local/bin` | next rebuild of the chain | +| `/usr/local/bin/turnkey-mysql-install-perf-info-schemas` | `common`, `overlays/mysql/usr/local/bin` | next rebuild of the chain | +| `turnkey-sysinfo`, `turnkey-version`, `turnkey-detect-virt` | Debian packages `turnkey-sysinfo`, `turnkey-version` | tracker#13, by replacing the packages | + +The two `keel-wordpress` ones change now because that appliance's own overlay +writes them, so they need no core rebuild: the recipe is rebuilt, one layer is +republished, and the chain under it is untouched. + +The middle two are a **correction to tracker#12's table**, which calls them +"inherited, build time". They are not inherited in the sense of being outside +this project's custody. Both are ordinary files in `Keel-Linux/common`, a +repository of this organization, reaching the image through `COMMON_OVERLAYS` +(`php.mk` and `mysql.mk` each add their overlay) and `fab-apply-overlay`. The +policy applies to them in full. What makes them wait is not ownership but +blast radius: `common` is under every appliance, so renaming there is a +rebuild of the whole chain, and it is done as part of a deliberate rebuild +rather than on its own. `turnkey-mysql-install-perf-info-schemas` also has a +caller inside `common` itself, +`overlays/mysql/usr/lib/confconsole/plugins.d/System_Settings/Mysql_perf_info.py`, +which moves in the same commit. + +## How the symlink is made, and how that was checked + +**In the overlay, committed to git.** Not `ln -s` in `conf.d/main`. + +`fab-apply-overlay` is `cp -TdR OVERLAY DEST` (`cmd_apply_overlay` in fab), +and `-d` is `--no-dereference --preserve=links`, so a symlink in an overlay +arrives in the image as a symlink. Git stores it as a symlink too, mode +`120000`, so the repository says plainly what the appliance will have. The +layer tarball is created and extracted by `tar`, which carries symlinks +natively. + +This was checked by doing it, not by reading the flags, because +docs/traps.md records "asserting the configuration is not asserting the +behaviour" as a defect this project keeps repeating. `tests/wrappers.bats` of +keel-wordpress copies the overlay with the same `cp -TdR` the build runs, +**twice** — that recipe applies its overlay twice, once through +`COMMON_OVERLAYS` and once as the product-local `ROOT_OVERLAY`, and a second +copy over an existing link has to leave a link and not a copy of its target — +and then *runs the copied `turnkey-wp`* and checks the command it produced. +`tests/v19.sh` does the same thing on a booted appliance: `turnkey-wp` is +asked for the core version and the site URL that `keel-wp` has just reported, +and the updater's root guard is required to hold under the old name too. +`test -L` says a link exists; it does not say the appliance still answers to +the old name. + +The alternative, `ln -sf` in `conf.d/main`, was rejected for three reasons: it +puts the fact in a build script instead of in the tree the reader is looking +at; it runs only at build time, so a rebuild is needed to notice it is +missing; and it cannot be tested without a chroot, while an overlay file is +tested by copying a directory. + +## Justification (three parts, brief section 10) + +1. **Why the present state does not hold.** The appliance speaks another + distribution's name in the commands an operator types every day, and for + two of them that name is written by this project, in this project's + repository, by a recipe this project maintains. That is not inherited + surface, it is ours, and leaving it is a choice we would be making every + release. +2. **Whether a plain rename would do.** No. It breaks every script written + against the old name and every command in TurnKey's documentation, and it + breaks them at a distance, long after the upgrade, with an error that does + not name the replacement. The project's compatibility claim (0008) is not + compatible with that. The opposite — keeping the `turnkey-*` name as the + real command and adding a Keel alias — was also considered and rejected: + two names with the wrong one authoritative means the documentation, the + error messages and the tests all keep saying somebody else's name, which + is the thing being fixed. +3. **Why this is better.** A symlink costs nothing at run time, nothing in the + image and one line in the overlay. The Keel name is what the documentation, + the recipes and the tests use, so the appliance describes itself by its own + name; the old name stays a working entry point for as long as anyone points + it at one. If the compatibility names are ever dropped, it is a deliberate + decision with its own note and its own deprecation, not a side effect of a + rename. + +## Consequences + +- Documentation, recipes, tests and error messages use the Keel name. A + command that reports its own name reports the one that was typed, so an + operator who ran `turnkey-wordpress-update` is not told about a command + they did not run. +- A call site left on the old name still works, which is exactly why it is + easy to miss and why the gate cannot catch it. Finding them is `grep -rn` + over the repository — README, tests, `conf.d`, overlays — and not a green + build. +- The compatibility names are covered by tests that run them, in every + repository that has a pair. A test that only reads the link does not + discharge this note. +- New commands get one name, the Keel one. This note is about names that + already exist; nothing new is born with a `turnkey-*` alias. +- 0014 keeps `/etc/turnkey_version` for the same compatibility reason, and the + changelog source names (`turnkey-wordpress-19.0`) are untouched here: they + are what `make-release-deb.py` and `turnkey-version.py` read, so they belong + to 0014's question and not to this one. From 8cd92a4c61d70e050b75c6c158f7a93679cdb3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20M=C3=A9ndez?= Date: Mon, 28 Sep 2026 04:37:44 +0000 Subject: [PATCH 2/3] docs: 0015 covers the commands our own packages install, and corrects the cp claim Review of #3 raised one HIGH: the note's inventory contradicted the note's own scope rule, and in the direction that makes a contributor under-apply the policy. The rule covers "a script installed by a package this project builds"; the table listed only the two keel-wordpress overlay files, the two in common and the foreign packages going to tracker#13. So it handled somebody else's packages and silently dropped the ones we build. Five commands were missing, all shipping on every appliance: turnkey-init, turnkey-sudoadmin, turnkey-install-security-updates and bin/turnkey-init-fence from inithooks, and turnkey-lexicon from confconsole. Both packages carry a +keel version, both are built from this organization's forks, and keel-wordpress's Makefile already names them among "the project's own packages". turnkey-init is the most operator-facing command on the machine. Two more were missing from common, turnkey-artisan and turnkey-composer, in scope by the rule though nothing includes laravel.mk or composer.mk yet; and unit-mariadb carries a byte-identical second copy of turnkey-mysql-install-perf-info-schemas, same blob, which the table attributed to common alone, so anybody following it would rename one of two copies. The inventory is now fifteen names grouped by what puts the file on the machine, because that is what decides when each can move, with eleven marked as ours. turnkey-make-ssl-cert from turnkey-ssl is listed too, as explicitly out of scope, so the next reader does not have to work that out again. And the section closes by saying the rule wins when the two disagree, since a table is a measurement of one day and this one has now been corrected three times. Second finding, a factual error worth more here than in code because a note is applied without asking: -d is not what preserves the symlink. -P is already the default under -R and only -L dereferences, so what -d buys is --preserve=links, which is hard links. As written the note would have taught that a copy without -d flattens links. Corrected with the measurement, and keel-wordpress now asserts the real property. Also from the review: the Decision section says the link is relative and why an absolute one breaks the build time caller, and that the Keel name is the turnkey- prefix replaced by keel- and nothing else, both of which were open questions a reader would have had to guess; the Consequences bullet about tests says "must be covered" rather than describing a state that is true of one repository; and the reverse dependency provenance says the container throughout rather than switching to the build host mid-section. --- docs/decisions/0015-operator-command-names.md | 210 ++++++++++++++---- 1 file changed, 166 insertions(+), 44 deletions(-) diff --git a/docs/decisions/0015-operator-command-names.md b/docs/decisions/0015-operator-command-names.md index a362693..ed830d4 100644 --- a/docs/decisions/0015-operator-command-names.md +++ b/docs/decisions/0015-operator-command-names.md @@ -12,6 +12,15 @@ Where such a command already exists under a `turnkey-*` name: - the **`turnkey-*` name is kept, as a symlink to it**; - **both keep working**, and neither is documented as deprecated. +Two details, because the natural choice is wrong in one of them and unstated +in the other. The Keel name is the `turnkey-` prefix replaced by `keel-` and +nothing else: `turnkey-wp` becomes `keel-wp`, `turnkey-init` becomes +`keel-init`. And **the link is relative** — `turnkey-wp -> keel-wp`, not +`-> /usr/local/bin/keel-wp`. An absolute link does not resolve inside +`fab-chroot`, so a build time caller such as `conf.d/main` stops finding the +command; keel-wordpress asserts the relative form for exactly that reason, and +making it absolute fails three of that repository's tests. + This is a general policy, not a per-appliance choice. It applies to every operator facing command a repository of this organization **writes and names itself**: a file in an appliance overlay, a file in the `common` overlays, a @@ -28,9 +37,15 @@ and a rename with no link is exactly that loss — it fails at the moment the operator needs the command, with `command not found` and no hint of a new name. -## What a `turnkey-*` name owned by a Debian package does instead +## What a `turnkey-*` name owned by somebody else's package does instead + +Nothing in this note. This section is about a package **this project does not +build** — the distinction matters, and getting it the wrong way round is the +mistake the first version of this note made. A command from a package with a +`+keel` version is ours, the rule applies to it directly, and it is in the +table below. What follows is only about the rest. -Nothing in this note. `turnkey-sysinfo` and `turnkey-version` are shipped by +`turnkey-sysinfo` and `turnkey-version` are shipped by the Debian packages of the same name, and a dpkg-owned file cannot simply become a symlink: the next upgrade of the package restores the file, and in the meantime dpkg either reports the divergence or replaces the link without @@ -52,52 +67,147 @@ go and fix. One correction to the inventory that raised this, Keel-Linux/tracker#12: `turnkey-sysinfo` ships **two** commands, not one. Its dpkg file list on the -build host is `/usr/bin/turnkey-sysinfo`, `/usr/bin/turnkey-detect-virt`, the -`libsysinfo` Python package it imports and the motd fragment under -`/usr/share/turnkey-sysinfo/contrib`. `turnkey-detect-virt` was missed, so the -table's five commands are really six. tracker#13 has to cover both names and -the library, because replacing only `turnkey-sysinfo` leaves a `keel-sysinfo` -calling a `turnkey-detect-virt` nobody owns. +`wordpress-demo` container is `/usr/bin/turnkey-sysinfo`, +`/usr/bin/turnkey-detect-virt`, the `libsysinfo` Python package it imports and +the motd fragment under `/usr/share/turnkey-sysinfo/contrib`. +`turnkey-detect-virt` was missed. tracker#13 has to cover both names, the +library and the motd fragment, because replacing only `turnkey-sysinfo` +leaves a `keel-sysinfo` calling a `turnkey-detect-virt` nobody owns. ## Which commands this changes now, and which wait -The five rows of tracker#12, re-measured: +tracker#12 measured five commands on the `wordpress-demo` container. That +inventory is where this note started and it is **not** the scope: the rule +above is. Applying the rule to this organization's repositories on 2026-09-28 +finds **fifteen** distinct `turnkey-*` names, **eleven of them ours**. The +tables below are the whole of what the rule reaches today, grouped by what +puts the file on the machine, because that is what decides when each one can +move. + +### Written by an appliance overlay -| Command | Where it really comes from | When | +| Command | Repository | When | | --- | --- | --- | | `/usr/local/bin/turnkey-wp` | `keel-wordpress`, `overlay/usr/local/bin` | **now** | | `/usr/local/sbin/turnkey-wordpress-update` | `keel-wordpress`, `overlay/usr/local/sbin` | **now** | -| `/usr/local/bin/turnkey-php` | `common`, `overlays/php/usr/local/bin` | next rebuild of the chain | -| `/usr/local/bin/turnkey-mysql-install-perf-info-schemas` | `common`, `overlays/mysql/usr/local/bin` | next rebuild of the chain | -| `turnkey-sysinfo`, `turnkey-version`, `turnkey-detect-virt` | Debian packages `turnkey-sysinfo`, `turnkey-version` | tracker#13, by replacing the packages | +| `/usr/local/bin/turnkey-mysql-install-perf-info-schemas` | `unit-mariadb`, `overlay/usr/local/bin` | with the `common` copy below | + +The first two change now because the appliance's own overlay writes them and +no core rebuild is involved: the recipe is rebuilt, one layer is republished, +and the chain under it is untouched. That is Keel-Linux/keel-wordpress#7. + +The third is in this group by where it lives and in the next group by when it +moves. `unit-mariadb/overlay/usr/local/bin/turnkey-mysql-install-perf-info-schemas` +is a **byte-identical second copy** of the `common` file — the same git blob, +`c8f185b2` — so the two move in one change, or an appliance built from the +unit keeps the old name while one built from `common` does not. Anybody +renaming that command by following the `common` row alone will rename one of +two copies. + +### Written by the `common` overlays -The two `keel-wordpress` ones change now because that appliance's own overlay -writes them, so they need no core rebuild: the recipe is rebuilt, one layer is -republished, and the chain under it is untouched. +| Command | Overlay | Reached through | When | +| --- | --- | --- | --- | +| `/usr/local/bin/turnkey-php` | `overlays/php` | `php.mk` | next rebuild of the chain | +| `/usr/local/bin/turnkey-mysql-install-perf-info-schemas` | `overlays/mysql` | `mysql.mk` | next rebuild of the chain | +| `/usr/local/bin/turnkey-artisan` | `overlays/artisan` | `laravel.mk` | when something includes it | +| `/usr/local/bin/turnkey-composer` | `overlays/composer` | `composer.mk` | when something includes it | -The middle two are a **correction to tracker#12's table**, which calls them +The first two are a **correction to tracker#12's table**, which calls them "inherited, build time". They are not inherited in the sense of being outside -this project's custody. Both are ordinary files in `Keel-Linux/common`, a -repository of this organization, reaching the image through `COMMON_OVERLAYS` -(`php.mk` and `mysql.mk` each add their overlay) and `fab-apply-overlay`. The -policy applies to them in full. What makes them wait is not ownership but -blast radius: `common` is under every appliance, so renaming there is a -rebuild of the whole chain, and it is done as part of a deliberate rebuild -rather than on its own. `turnkey-mysql-install-perf-info-schemas` also has a -caller inside `common` itself, +this project's custody: both are ordinary tracked `100755` files in +`Keel-Linux/common`, a repository of this organization, reaching the image +through `COMMON_OVERLAYS` and `fab-apply-overlay`, and on the appliance +`dpkg -S` reports them owned by no package at all. The policy applies to them +in full. What makes them wait is not ownership but blast radius: `common` is +under every appliance, so renaming there is a rebuild of the whole chain and +belongs to a deliberate one. `turnkey-mysql-install-perf-info-schemas` also +has a caller inside `common` itself, `overlays/mysql/usr/lib/confconsole/plugins.d/System_Settings/Mysql_perf_info.py`, which moves in the same commit. +`turnkey-artisan` and `turnkey-composer` ship on no Keel appliance today, +because nothing includes `laravel.mk` or `composer.mk`. They are listed +anyway: `turnkey-artisan` is the same `runuser` shape as `turnkey-wp`, and a +name that is only found again when an appliance starts shipping it is a name +that gets shipped under the wrong one. + +### Installed by a package this project builds + +Versions are the ones installed on the `wordpress-demo` container on +2026-09-28; both repositories are already further ahead on `main`. + +| Command | Package | Version on the appliance | +| --- | --- | --- | +| `/usr/sbin/turnkey-init` | `inithooks` | `2.3.6+keel4` | +| `/usr/sbin/turnkey-sudoadmin` | `inithooks` | `2.3.6+keel4` | +| `/usr/sbin/turnkey-install-security-updates` | `inithooks` | `2.3.6+keel4` | +| `/usr/lib/inithooks/bin/turnkey-init-fence` | `inithooks` | `2.3.6+keel4` | +| `/usr/bin/turnkey-lexicon` | `confconsole` | `2.2.3+keel2` | + +**These are in scope and they were missing from the first version of this +note.** The third clause of the rule above is "a script installed by a package +this project builds", and both packages carry a `+keel` suffix: they are built +from `Keel-Linux/inithooks` and `Keel-Linux/confconsole`, whose trees hold +`turnkey-init`, `turnkey-sudoadmin`, `turnkey-install-security-updates`, +`bin/turnkey-init-fence` and `turnkey-lexicon` as their own source files, and +keel-wordpress's `Makefile` names both among "the project's own packages". +`turnkey-init` is the most operator-facing command on the machine — it is what +an operator types to run the first boot configuration again. + +They wait on the same rebuild as `common`, and each needs more than a rename. +`turnkey-init-fence` is not on `PATH` and is not a command an operator types, +but the name is also `/etc/default/turnkey-init-fence`, the systemd unit +`turnkey-init-fence.service`, the firstboot hooks `30turnkey-init-fence` and +`97turnkey-init-fence-disable`, and a `htdocs` directory; the compatibility +rule covers the command, and the unit and conffile names are a packaging +question for whoever does that work, not something this note settles. + +### Owned by a package somebody else builds + +| Command | Package | Disposition | +| --- | --- | --- | +| `turnkey-sysinfo`, `turnkey-detect-virt` | `turnkey-sysinfo` 1.1.0 | tracker#13, by replacing the package | +| `turnkey-version` | `turnkey-version` 1.1.3 | tracker#13, by replacing the package | +| `/usr/bin/turnkey-make-ssl-cert` | `turnkey-ssl` 3.1.1 | **out of scope**, and stays as it is | + +Neither `turnkey-sysinfo`, `turnkey-version` nor `turnkey-ssl` carries a +`+keel` suffix, so all three are somebody else's build and fall under the +carve-out. The first two are being replaced for the reasons in the previous +section. `turnkey-ssl` is not, and nothing in this note asks for it to be: it +is inherited surface and keeps its name until a decision says otherwise. + +### If this table and the rule ever disagree + +The rule wins. A table is a measurement of one day and this one has already +been corrected twice; the rule at the top of this note is the policy. A +command that meets it and is not listed here is in scope, and the right fix is +to add the row. + ## How the symlink is made, and how that was checked **In the overlay, committed to git.** Not `ln -s` in `conf.d/main`. -`fab-apply-overlay` is `cp -TdR OVERLAY DEST` (`cmd_apply_overlay` in fab), -and `-d` is `--no-dereference --preserve=links`, so a symlink in an overlay -arrives in the image as a symlink. Git stores it as a symlink too, mode -`120000`, so the repository says plainly what the appliance will have. The -layer tarball is created and extracted by `tar`, which carries symlinks -natively. +`fab-apply-overlay` is `cp -TdR OVERLAY DEST` (`cmd_apply_overlay` in fab). +**`-R` copies a symlink as a symlink unless `-L` is given, and `-d` +additionally preserves hard links**, so a symlink in an overlay arrives in the +image as a symlink. Git stores it as a symlink too, mode `120000`, so the +repository says plainly what the appliance will have. The layer tarball is +created and extracted by `tar`, which carries symlinks natively. + +The attribution matters, because a copy step is the kind of thing that gets +written again from a note like this one. `-P` is already the default under +`-R`; only `-L` dereferences. Measured with coreutils 9.7: + + cp -TR → link -> real symlink kept, hard link split (nlink 1) + cp -TdR → link -> real symlink kept, hard link kept (nlink 2) + cp -TLR → link a second regular file: this is the one that + flattens + +So what `-d` contributes to the overlay step is `--preserve=links`, which is +about **hard** links. The property this policy depends on is the absence of +`-L`. A note that said otherwise would get `-d` added where it does nothing, +or a sound mechanism rejected for lacking it. This was checked by doing it, not by reading the flags, because docs/traps.md records "asserting the configuration is not asserting the @@ -106,12 +216,18 @@ keel-wordpress copies the overlay with the same `cp -TdR` the build runs, **twice** — that recipe applies its overlay twice, once through `COMMON_OVERLAYS` and once as the product-local `ROOT_OVERLAY`, and a second copy over an existing link has to leave a link and not a copy of its target — -and then *runs the copied `turnkey-wp`* and checks the command it produced. +and then *runs the copied `turnkey-wp`* and checks the command it produced. A +further test pins the paragraph above rather than only asserting it in prose: +a plain `cp -TR`, without `-d`, still yields a working `turnkey-wp`, and +`cp -TLR` turns it into a second regular file. `tests/v19.sh` does the same thing on a booted appliance: `turnkey-wp` is -asked for the core version and the site URL that `keel-wp` has just reported, -and the updater's root guard is required to hold under the old name too. -`test -L` says a link exists; it does not say the appliance still answers to -the old name. +asked for the core version and the site URL, each compared against a literal +the script already holds rather than against a second `keel-wp` call, and the +updater's root guard is required to hold under the old name too. Comparing two +command substitutions would have passed as `test "" = ""` with wp-cli broken +and both sides empty, which is the same trap in a smaller shape. `test -L` +says a link exists; it does not say the appliance still answers to the old +name. The alternative, `ln -sf` in `conf.d/main`, was rejected for three reasons: it puts the fact in a build script instead of in the tree the reader is looking @@ -122,11 +238,15 @@ tested by copying a directory. ## Justification (three parts, brief section 10) 1. **Why the present state does not hold.** The appliance speaks another - distribution's name in the commands an operator types every day, and for - two of them that name is written by this project, in this project's - repository, by a recipe this project maintains. That is not inherited - surface, it is ours, and leaving it is a choice we would be making every - release. + distribution's name in the commands an operator types every day, and most + of those names are ours. The inventory below is fifteen distinct names + across this organization's repositories, **eleven of them written or built + by this project**: two by keel-wordpress's own overlay, four by `common`, + five by `inithooks` and `confconsole`. Thirteen of the fifteen are present + on a `wordpress-demo` container, nine of those ours, and `turnkey-init` — + what an operator types to run the first boot configuration again — is one + of them. That is not inherited surface, it is ours, and leaving it is a + choice we would be making every release. 2. **Whether a plain rename would do.** No. It breaks every script written against the old name and every command in TurnKey's documentation, and it breaks them at a distance, long after the upgrade, with an error that does @@ -154,9 +274,11 @@ tested by copying a directory. easy to miss and why the gate cannot catch it. Finding them is `grep -rn` over the repository — README, tests, `conf.d`, overlays — and not a green build. -- The compatibility names are covered by tests that run them, in every - repository that has a pair. A test that only reads the link does not - discharge this note. +- The compatibility names **must be covered** by tests that run them, in + every repository that has a pair. A test that only reads the link does not + discharge this note. Today keel-wordpress has such tests and nothing else + does; the four in `common` and the five from `inithooks` and `confconsole` + are owed them when they move. - New commands get one name, the Keel one. This note is about names that already exist; nothing new is born with a `turnkey-*` alias. - 0014 keeps `/etc/turnkey_version` for the same compatibility reason, and the From 41871ea99fc191498c58efd9b944d03d51f66f39 Mon Sep 17 00:00:00 2001 From: navigator Date: Tue, 29 Sep 2026 03:33:39 +0000 Subject: [PATCH 3/3] docs: 0015 without em dashes Brief section 10 asks for commas, colons, parentheses or semicolons in documentation; the note carried fourteen em dashes. Wording otherwise unchanged. --- docs/decisions/0015-operator-command-names.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/decisions/0015-operator-command-names.md b/docs/decisions/0015-operator-command-names.md index ed830d4..afbb347 100644 --- a/docs/decisions/0015-operator-command-names.md +++ b/docs/decisions/0015-operator-command-names.md @@ -8,14 +8,14 @@ Status: decided by the maintainer A command an operator types on a Keel appliance carries this project's name. Where such a command already exists under a `turnkey-*` name: -- the **Keel name is the real command** — the file with the code in it; +- the **Keel name is the real command**: the file with the code in it; - the **`turnkey-*` name is kept, as a symlink to it**; - **both keep working**, and neither is documented as deprecated. Two details, because the natural choice is wrong in one of them and unstated in the other. The Keel name is the `turnkey-` prefix replaced by `keel-` and nothing else: `turnkey-wp` becomes `keel-wp`, `turnkey-init` becomes -`keel-init`. And **the link is relative** — `turnkey-wp -> keel-wp`, not +`keel-init`. And **the link is relative**: `turnkey-wp -> keel-wp`, not `-> /usr/local/bin/keel-wp`. An absolute link does not resolve inside `fab-chroot`, so a build time caller such as `conf.d/main` stops finding the command; keel-wordpress asserts the relative form for exactly that reason, and @@ -33,14 +33,14 @@ keeps its name in 0014. Compatibility with TurnKey appliances is a stated property of this project (0008: the fork is kept upstream-compatible on purpose). An operator who pasted a command out of TurnKey's documentation, or who wrote a script against `turnkey-wp` last year, must not silently lose it, -and a rename with no link is exactly that loss — it fails at the moment the +and a rename with no link is exactly that loss: it fails at the moment the operator needs the command, with `command not found` and no hint of a new name. ## What a `turnkey-*` name owned by somebody else's package does instead Nothing in this note. This section is about a package **this project does not -build** — the distinction matters, and getting it the wrong way round is the +build**; the distinction matters, and getting it the wrong way round is the mistake the first version of this note made. A command from a package with a `+keel` version is ours, the rule applies to it directly, and it is in the table below. What follows is only about the rest. @@ -98,8 +98,8 @@ and the chain under it is untouched. That is Keel-Linux/keel-wordpress#7. The third is in this group by where it lives and in the next group by when it moves. `unit-mariadb/overlay/usr/local/bin/turnkey-mysql-install-perf-info-schemas` -is a **byte-identical second copy** of the `common` file — the same git blob, -`c8f185b2` — so the two move in one change, or an appliance built from the +is a **byte-identical second copy** of the `common` file (the same git blob, +`c8f185b2`), so the two move in one change, or an appliance built from the unit keeps the old name while one built from `common` does not. Anybody renaming that command by following the `common` row alone will rename one of two copies. @@ -152,7 +152,7 @@ from `Keel-Linux/inithooks` and `Keel-Linux/confconsole`, whose trees hold `turnkey-init`, `turnkey-sudoadmin`, `turnkey-install-security-updates`, `bin/turnkey-init-fence` and `turnkey-lexicon` as their own source files, and keel-wordpress's `Makefile` names both among "the project's own packages". -`turnkey-init` is the most operator-facing command on the machine — it is what +`turnkey-init` is the most operator-facing command on the machine: it is what an operator types to run the first boot configuration again. They wait on the same rebuild as `common`, and each needs more than a rename. @@ -213,9 +213,9 @@ This was checked by doing it, not by reading the flags, because docs/traps.md records "asserting the configuration is not asserting the behaviour" as a defect this project keeps repeating. `tests/wrappers.bats` of keel-wordpress copies the overlay with the same `cp -TdR` the build runs, -**twice** — that recipe applies its overlay twice, once through +**twice**: that recipe applies its overlay twice, once through `COMMON_OVERLAYS` and once as the product-local `ROOT_OVERLAY`, and a second -copy over an existing link has to leave a link and not a copy of its target — +copy over an existing link has to leave a link and not a copy of its target; and then *runs the copied `turnkey-wp`* and checks the command it produced. A further test pins the paragraph above rather than only asserting it in prose: a plain `cp -TR`, without `-d`, still yields a working `turnkey-wp`, and @@ -243,16 +243,16 @@ tested by copying a directory. across this organization's repositories, **eleven of them written or built by this project**: two by keel-wordpress's own overlay, four by `common`, five by `inithooks` and `confconsole`. Thirteen of the fifteen are present - on a `wordpress-demo` container, nine of those ours, and `turnkey-init` — - what an operator types to run the first boot configuration again — is one + on a `wordpress-demo` container, nine of those ours, and `turnkey-init` + (what an operator types to run the first boot configuration again) is one of them. That is not inherited surface, it is ours, and leaving it is a choice we would be making every release. 2. **Whether a plain rename would do.** No. It breaks every script written against the old name and every command in TurnKey's documentation, and it breaks them at a distance, long after the upgrade, with an error that does not name the replacement. The project's compatibility claim (0008) is not - compatible with that. The opposite — keeping the `turnkey-*` name as the - real command and adding a Keel alias — was also considered and rejected: + compatible with that. The opposite, keeping the `turnkey-*` name as the + real command and adding a Keel alias, was also considered and rejected: two names with the wrong one authoritative means the documentation, the error messages and the tests all keep saying somebody else's name, which is the thing being fixed. @@ -272,7 +272,7 @@ tested by copying a directory. they did not run. - A call site left on the old name still works, which is exactly why it is easy to miss and why the gate cannot catch it. Finding them is `grep -rn` - over the repository — README, tests, `conf.d`, overlays — and not a green + over the repository (README, tests, `conf.d`, overlays) and not a green build. - The compatibility names **must be covered** by tests that run them, in every repository that has a pair. A test that only reads the link does not