fix: detect stale Kimaki dispatch helpers - #305
Merged
Conversation
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.
Summary
www-dataand the adopted service user can traverse the registered wrapper path.root_repair_requiredresult plus an exact shell-safe root repair command when non-root cannot inspect, validate, or repair root-owned artifacts.Root cause and production timeline
Production helper artifacts were installed as root at 2026-06-27 01:24 UTC. PR #243, which added the required
www-data -> SERVICE_USERsudoers grant, merged later at 2026-06-27 01:56 UTC.The non-root upgrade fast path checked only that the adopted service user could invoke the target directly. That path bypassed the registered wrapper and never inspected the root-owned sudoers file, so the pre-#243 service-user-only grant was repeatedly certified as healthy while scheduled WordPress dispatch from
www-datacontinued failing.Why #240 and #243 did not stick
#240 established the wrapper-based dispatch path, and #243 corrected the generated sudoers template to include
www-data. Neither changed the non-root upgrade health oracle: an already-installed target that worked for the service user still caused an early return before current wrapper, target, or sudoers content was compared. Because non-root upgrades could not rewrite the root-owned files, the corrected #243 template never reached this host.Ownership boundary
wp-coding-agents owns generation, installation, upgrade health, and repair instructions for the Kimaki wrapper, target, and sudoers artifacts. Homeboy may invoke an upgrade, coordinate a deployment, or consume its output, but it does not own or infer the health of these wp-coding-agents installation artifacts. This PR keeps the repair signal and validation in the owning bridge installer rather than adding Homeboy-specific behavior.
Behavior
Before:
SERVICE_USER -> target --versionwas treated as complete helper health.www-data -> wrapper -> SERVICE_USERexecution was not tested.After:
www-dataand the adopted service user.{"status":"root_repair_required",...}and an exactsudo -- .../upgrade.sh --kimaki-only --wp-path ... --kimaki-unit ...repair command; the final summary repeats the required action.visudois available, compare installed bytes with generated content, and execute the wrapper through both caller identities.Tests
tests/kimaki-dispatch-helper-health.shand a dedicated CI job.www-dataand service-user grants, caller validation, and deduplication when the service user iswww-data.git diff --check, and focusedshellcheckon modified scripts.Remaining privilege limitations
A normal service user commonly cannot read
/etc/sudoers.dor impersonatewww-data; that is now reported as root repair required rather than guessed healthy. The root repair remains an explicit operator action. This PR does not merge, release, deploy, restart Kimaki, or verify production cron dispatch; production verification follows the eventual authorized merge/release/deploy.Closes #304