Ambient box credential: FDE identity for in-container interactive sessions - #174
Merged
Conversation
…sions sail-agent-principals closed the forgeable SAIL_ACTOR hole but defined identity only for sail-launched runs; every interactive session (an engineer's SSH shell, an IDE-spawned agent) became nobody and the spec CLI 401s fleet-wide after upgrade. Possession of the box is the FDE identity — the container is enterable only with the FDE's SSH key — so the socket now honors an ambient credential provisioned beside it. One hashed single-row credential per devbox (BoxCredentialStore), reconciled with the plaintext file in the shared socket mount by BoxCredentialFile at server start: missing, tampered, rotated, or rebound state all self-heal. LocalApiRouter resolves run credentials first (a launched agent is always its principal), then the box credential to the FDE's roster role — fail closed when the handle has left the roster. Events stay run-only. The spec script falls back to the ambient file when SAIL_RUN_CREDENTIAL is unset, and a best-effort boot sweep refreshes helpers in every running project container, so enforcement and provisioning ship in the same hop.
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.
Why
sail-agent-principals(v0.16.0) rightly killed the forgeableSAIL_ACTOR, but it defined identity only for sail-launched runs. Every interactive session — an FDE's SSH shell into a project container, an IDE-spawned agent — became nobody, and the in-containerspecCLI 401s in every project the moment the host upgrades. Interactive sessions are the dominant mode for spec work.Trust model: possession of the box is the FDE identity — a container lives on one FDE's devbox and is enterable only with that FDE's SSH key, the same key that already is the Sail CLI identity on the host lane.
What
BoxCredentialStore: one hashed single-row credential per devbox (sailbox_<64-hex>);replaceatomically retires the old plaintext,resolvemaps plaintext → handle. New table rides the post-baseline migration lane.BoxCredentialFile: self-healing reconciler for the plaintext file besideapi.sockin the shared bind-mounted dir — ambient in every container with zero per-container work. Missing/tampered/rotated/rebound state all converge on the next server start.LocalApiRouter: sealedCaller(Run|Box); run credentials resolve first (a launched agent is always its principal), then the box credential → the FDE's real roster role (fail closed when the handle left the roster). Spec/content/message writes author as the FDE through the sameSpecPolicy;whoamireflects the box identity; events stay run-only (403).specscript: falls back to the ambient file whenSAIL_RUN_CREDENTIALis unset; new staleness marker in theContainerSailSetupchain.ContainerSetupSweepat server start: best-effort refresh of the socket mount + helper scripts in every running catalog container, so enforcement and provisioning ship in the same hop — recovery from the current fleet-wide 401 is exactly onesail upgrade. (The mount force-refresh also heals reboot-stranded sockets.)Verification
box.credentialfrom the mount — whoami as the FDE, posts a spec message attributed to the FDE, forgedsailbox_still 401smvn -Pintegration -Dsail.it.requireIncus=false clean verifygreen (all JaCoCo + Spotless gates)