[WIP] do not review — feat(minimald): GitHub-integrated sessions (spec 10) - #1130
Draft
norrietaylor wants to merge 8 commits into
Draft
[WIP] do not review — feat(minimald): GitHub-integrated sessions (spec 10)#1130norrietaylor wants to merge 8 commits into
norrietaylor wants to merge 8 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Spec 10. Daemon-held GitHub App auth over the OAuth device flow, a mediated git/api facade so no token ever enters the sandbox, repo pre-priming at activation, scope consent with reuse-or-mint, and a client-driven PR-on-exit prompt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Domain types, an on-disk grant store (0600, atomic writes), the OAuth device-flow client, a REST client (authenticated user, App installation, pull requests), leak-proof `gitops` (env-only credential injection plus an option-injection guard), and the token-refresh state machine (single-flight, write-ahead rotation). `test-support` ships an in-process mock GitHub and the `github-mock` binary so the daemon's auth and git paths can be exercised without touching real GitHub. Each consumer's manifest declares the dependency here rather than in its own commit, so `Cargo.lock` is coherent with every manifest from this commit on and the series stays bisectable. Default features are I/O-free — no reqwest — so `mfile` and `minimal` can depend on the crate without pulling an HTTP stack. The App client id is baked in at build time: `build.rs` registers `MINIMAL_GITHUB_CLIENT_ID` as a rebuild trigger so a rotated id is never served from a stale build cache, and `config.rs` reads it via `option_env!`. Runtime `MINIMALD_GITHUB_CLIENT_ID` still takes precedence, for GHES, the mock server, and self-hosted Apps. An installed user has no other channel: there is no daemon config file, `minimald` is autospawned rather than run from a service unit, and on macOS it runs as the microVM's init with an empty environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`GithubBeginLogin`, `GithubPollLogin`, `GithubStatus`, `GithubListAuths`,
and `GithubLogout`.
Also fixes `Errorable`, which hid every daemon-side error. It is
`#[serde(untagged)]`, so serde tries variants in declaration order, and the
response types default all their fields — so with `Ok` first a daemon
`{"error": ".."}` payload decoded as `Ok(Default::default())` and the client
reported a blank success for a refused RPC. `min github login` against an
unconfigured daemon printed an empty verification URI instead of naming the
unset variable. `Err` is now declared first; no response type carries an
`error` field, so this is unambiguous. The bug also affected
`ConfigureLoadout` and `FinalizeSession`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Per-repo specs and scope overrides for repo pre-priming, validated at load time so a malformed scope is a config error rather than a runtime auth failure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… facade Builds one `GithubService` at daemon startup and shares it across every session, dispatches the five auth RPCs through the `serve!` macro, and adds the `authorize()` choke point over session attrs. The `git%` facade isolates the token-bearing git leg from everything the sandbox controls: daemon-side git runs only in a daemon-authored bare mirror, with global and system config denied, and object transfer happens via `objects/info/alternates` plus plain-file ref writes rather than a git remote the sandbox could redirect. `APP_SLUG` names the org's registered App and builds the installation URL `min github status` prints; a mismatch there is invisible from inside the daemon, since only that URL breaks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drives the device flow through the daemon over SSH RPC, polling with a terminal spinner until the login resolves. Attach now runs ssh as a waited-on child rather than `exec()`ing into it, so control returns to the client once the session shell exits — the seam post-attach flows such as an exit prompt hook into. Keyboard signals are ignored while the child runs so Ctrl-C reaches the foreground process instead of killing the waiting client, and the child's status is propagated so the observable exit code matches the old `exec()`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Forwards the `MINIMAL_GITHUB_CLIENT_ID` repository variable from a workflow-level `env` block, so it reaches every build job — including the `minimald-linux-*` binaries that `build-release-initramfs` repacks as the guest daemon, which boots with an empty environment and could not be configured any other way. The reading side is `crates/github`. A repository variable, not a secret: a GitHub App client id is public, because the device flow is a public-client flow with no client secret. Unset resolves to the empty string, which reads as "no App configured", so a release cut before the variable is set still builds and ships inert. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The workspace is 30 crates now; the map still said 29 and omitted the row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
norrietaylor
force-pushed
the
claude/minimald-github-prd-r6ew53
branch
from
July 31, 2026 21:31
2e89634 to
295dfc3
Compare
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.
WIP — do not review. Successor to #996 (closed), same branch. Opened to keep
CI running against a real toolchain while the remaining spec-10 surface lands.
Spec 10 — GitHub-integrated minimald sessions
Implements the PRD at
docs/specs/10-spec-github-sessions/. Daemon-held GitHub Appauth (device flow), a mediated
min git/min apifacade so no token enters thesandbox, repo pre-priming at activation, scope consent + reuse-or-mint, and a
client-driven PR-on-exit prompt.
State
CI is green across all five lane aggregators.
mainis merged in; the branchcarries the whole
crates/githubengine (domain types, grant store, device flow,REST client, leak-proof
gitops, refresh state machine, mock GitHub), the daemonGithubServicewiring and auth RPCs, thegit%facade, and themin github login|status|logoutCLI.Fixed while getting CI green
Errorabledecoded every daemon error as a blankOk. The enum is#[serde(untagged)]withOktried first, and the response types default alltheir fields, so an
{"error": ..}payload deserialized asOk(Default).min github loginagainst an unconfigured daemon printedOpen and enter codeand then
error: missing login_idinstead of naming the unset variable. Thisalso hid errors on
ConfigureLoadoutandFinalizeSession.Erris nowdeclared first, with a regression test; verified end-to-end against a live
VM-backed daemon.
had no way to supply
MINIMALD_GITHUB_CLIENT_ID: no daemon config file,minimaldis autospawned rather than run from a service unit, and on macOS itruns as the microVM's init with an empty environment (
vm.rsforwards onlyRUST_LOG).crates/github/build.rsregisters the rebuild trigger,config.rsreads it viaoption_env!, andrelease.ymlforwards the repovariable. Runtime env still overrides, so the mock server and GHES keep working.
install_urltest asserted public GitHub's host while running against a mock.assert_no_token_on_diskgated ontest-support.minimald-rpctests; unusedfutures::StreamExtinenv.rs.Not yet implemented (follow-up)
api%facade verb, in-sandboxmin githelper, push/PR + prime RPC handlers,activate consent/prime wiring, PR-on-exit, redaction + no-token proof harnesses,
integration/e2e suites, docs. Deferred by design: MCP server proper,
on_destroyexecutor, egress enforcement, NG1–NG6.
Needs a maintainer action before the feature works for users
Set the
MINIMAL_GITHUB_CLIENT_IDrepository variable (Settings → Secrets andvariables → Actions → Variables). A GitHub App client id is public — the device
flow is a public-client flow with no client secret — so it is deliberately a
variable, not a secret. Unset builds ship inert and fail closed.
🤖 Generated with Claude Code
Note
Add GitHub-integrated sessions with device-flow auth to
minimaldandminCLIgithubcrate (Cargo.toml) providing domain types, OAuth device-flow client, token/secret handling, scope validation, on-disk grant storage with strict Unix permissions, and a feature-gated test mock server.min github login|status|logoutCLI subcommands in crates/minimal/src/github.rs;logininitiates device-flow via the daemon, polls for completion, and prints the verification URL and user code.GithubBeginLogin,GithubPollLogin,GithubStatus,GithubListAuths,GithubLogout) through minimald-rpc and minimald rpc dispatch to a sharedGithubServiceinitialized at daemon startup.mfilesessions with an optional[session.github]block (crates/mfile/src/lib.rs) carrying repos and scopes, validated on access rather than at parse time.git%facade requests are now dispatched viaSessionChannel::git_facadeand proxied to daemon-held GitHub credentials; unauthenticated sessions receive a clear error.Errorableserde variant ordering so{"error":…}payloads decode asErrinstead of a defaultedOk.min attachnow spawns ssh as a child process and waits for it (rather than exec-ing), ignoring SIGINT/SIGQUIT in the parent and propagating ssh's exit code using shell signal conventions.Macroscope summarized 2e89634. (Automatic summaries will resume when PR exits draft mode or review begins).