The runtime credential channel - #299
Open
zxgshawn wants to merge 7 commits into
Open
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.
Makes the dial token the only credential in a runtime's environment, and mints everything else on demand against it.
Two secrets used to ride the environment and expire there: the GitHub token (~1h) and the plugin artifact token (1h).
RuntimeManagerre-minted both on every acquisition, but Fly and velos discard the spec onget(let _ = spec;), so the environment is frozen at create — a runtime up for an hour holds a dead GitHub token, and a resumed machine comes back with the one it was born with. Nothing could renew either: no protocol message, and no substrate can rewrite a running machine's environment.The dial token is different — horsie mints it, horsie verifies it, it never expires — so it can be the root that fetches the rest. That was blocked by
horsie connectsigning with a per-process random secret the server had never seen, which made its runtimes' tokens meaningless to the server.The server now mints every dial token, shipped in
RuntimeSpec.envalongside the other server-minted values. No new endpoint or round trip. The CLI vendor's listener switches from HMAC verification to a lookup of tokens it issued — strictly stronger, since a token this vendor never handed out is unknown rather than merely unsigned.Bundle artifacts authenticate with that token, scoped to the account's installed bundles.
HORSIE_PLUGINS_TOKEN, the deployment-globalartifact_secret, andHORSIE_ARTIFACT_SECRETare deleted. Note the boundary this adds: the route previously had no account check at all, so any account's token fetched any account's artifact.GitHub moves to a
horsie-runtime git-credentialhelper installed viaGIT_CONFIG_*at startup, minting per operation from a new dial-token-authenticated endpoint scoped to the session's owngit_checkoutrepos.GITHUB_TOKENleaves the environment, andgit pushstarts working — the old clone passed a one-shothttp.extraHeaderand deliberately left nothing in.git/config.Two pre-existing bugs fixed along the way: no cloud vendor ever set the bundle base URL, so plugin bundles silently never worked on Fly or velos; and a sandboxed runtime could not exec its own binary, which the credential helper needs.
Not fixed, and worth stating: the agent's
bashinherits the runtime environment, so it can read the dial token and call these endpoints itself. The trust boundary is the runtime, not the process tree. What this buys is narrower — nothing expiring in the environment, no long-lived GitHub token in it, and revocation that takes effect on the next operation rather than an hour ago.Design and plan under
docs/superpowers/.