feat(apps): reconcile managed apps from the fleet desired state - #456
Open
Alexgodoroja wants to merge 1 commit into
Open
feat(apps): reconcile managed apps from the fleet desired state#456Alexgodoroja wants to merge 1 commit into
Alexgodoroja wants to merge 1 commit into
Conversation
Nodes converge their installed apps toward a desired-set document the authority writes into the fleet state mirror. The document arrives as an ordinary signed, revision-fenced state mutation, so managed app install adds no new command kind, endpoint, or inbound channel. The two-root design is the grant boundary. Grants exist only inside a signed bundle, never in the catalogue, so a node installs an unreviewed app into a staging root the supervisor does not scan: the binary is present, its manifest can be read and reported, and it cannot run. Promotion into the live install root happens only once the desired document accepts every grant the manifest declares -- and a catalogue republish that widens them demotes the app rather than silently keeping the wider capability set. Installation itself shells out to the pilotctl beside the daemon. pilotctl owns the only implementation of the catalogue trust chain, and a second verifier for a security boundary is the one thing that must not exist; AppInstaller keeps that swappable if the path is later extracted. The inventory is republished only when it actually changes: it lives in the state mirror, so a ticking timestamp would churn the revision the console fences its mutations on and invalidate in-flight installs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
| defer cancel() | ||
| // --force lets an install replace a wrong-version copy in place; the | ||
| // catalogue signature and sha256 gates still run either way. | ||
| command := exec.CommandContext(ctx, installer.BinaryPath, "appstore", "install", appID, "--force") |
| } | ||
| ctx, cancel := context.WithTimeout(ctx, installer.timeout()) | ||
| defer cancel() | ||
| command := exec.CommandContext(ctx, installer.BinaryPath, "appstore", "uninstall", appID, "--yes") |
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.
The node half of the fleet App Store. Pairs with
pilot-protocol/platform#61 — that PR ships the console and the desired-state
contract; without this one a managed node never acts on a queued install and
the store shows
installingindefinitely.How it works
Nodes converge their installed apps toward a desired-set document the authority
writes into the fleet state mirror. The document arrives as an ordinary signed,
revision-fenced state mutation, so managed app install adds no new command
kind, endpoint, or inbound channel.
The grant boundary
Grants exist only inside a signed bundle, never in the catalogue. So a node
installs an unreviewed app into a staging root the supervisor does not scan:
the binary is present, its manifest can be read and reported, and it cannot
run. Promotion into the live install root happens only once the desired
document accepts every grant the manifest declares — and a catalogue republish
that widens them demotes the app rather than silently keeping the wider set.
Installation
Shells out to the
pilotctlbeside the daemon.pilotctlowns the onlyimplementation of the catalogue trust chain — publisher signature, per-platform
bundle pin, sha256 verification, sideload clamping — and a second, subtly
different verifier for a security boundary is the one thing that must not
exist.
AppInstallerkeeps that swappable if the path is later extracted intoa library.
Inventory
Republished only when it actually changes. The report lives in the state
mirror, so a ticking timestamp would churn the revision the console fences its
mutations on and invalidate an operator's in-flight install.
Verification
gofmt,go build ./...andgo test ./internal/enterprisecontrol/areclean. Eleven tests cover the reconciler: staging on unreviewed grants,
promotion on acceptance, demotion when grants widen, partial-acceptance
refusal, removal, leaving hand-installed apps alone, install failure, a
document addressed to another node, and the revision-churn guard.
Not yet exercised against a live daemon end to end —
deploy/dev-mirror/connect-node.shin the platform PR is the path for that.