Commit Graph
3 Commits
Author SHA1 Message Date
mroberts d96f32d773 Resolve the repository from the invoking directory
A task included from the global mise config runs with the config root as its
working directory - $HOME - rather than the directory the user invoked it from.
Deriving the repository from the current directory therefore failed everywhere
except a project-level include, which defeats the point of installing the task
once and using it in every repository.

mise passes the real directory as MISE_ORIGINAL_CWD, so enter it before
resolving the repository, falling back to the current directory when the task
is run directly rather than through mise.
2026-07-30 14:35:40 -05:00
mroberts b03fcd6dd7 Mint GitHub App installation tokens instead of per-repo PATs
GitHub exposes no API to create a fine-grained PAT and no way to prefill the
creation form, so every repository meant hand-clicking a permission set and
remembering to rotate it. Installation tokens are API-mintable, so configuring
one GitHub App removes the per-repository work entirely.

A new 'app' subcommand records the App ID and private key path once. Setup then
resolves the installation for the repository, and run and refresh mint a fresh
token scoped to that single repository before every launch. Tokens expire in an
hour on their own, which retires manual rotation.

sbx secret set is invoked with --force because without it a second write prompts
for confirmation, reads the prompt from the stdin already consumed by the token,
cancels, and still exits 0 - leaving the previous, expired token in place.

The permission set is validated against GitHub's app-permissions schema. Notably
workflows has no read level, and write is required to push any commit touching
.github/workflows, which is a separate permission from actions.

Also corrects several sbx invocations that did not match the installed CLI:
--no-share-skills and --clone are not create flags, isolation is --branch; run
takes a sandbox name rather than --name; exec takes no -- separator; ls --quiet
replaces parsing tabular output; and the sandbox home is queried rather than
assumed to be /home/agent.

Adds a JWT test that verifies signatures against a generated public key and
confirms tampered input fails to verify.
2026-07-30 14:25:37 -05:00
mroberts d43abe693e Add repository-scoped AI sandbox mise task
Provides a shareable mise task, ai:sbx, that runs an AI coding agent in a
Docker Sandbox scoped to a single GitHub repository and a set of read-only
AWS roles.

The repository is derived from origin rather than configured, so the sandbox
identity cannot drift from the checkout in use. GitHub access is a
repository-scoped fine-grained PAT held in the sbx secret store and injected
by its host-side proxy, so the token is never exposed to the agent. The host
~/.aws directory and SSO token cache are never mounted; instead the host
exports short-lived credentials for approved read-only profiles and only
those land in the sandbox.

Host profiles are commonly suffixed to mark the grant (api-portal-readonly)
while Terraform references the account name (api-portal), so a trailing
-readonly is stripped when the profile is written into the sandbox. Two host
profiles that collapse to the same sandbox name are rejected during setup,
before any credentials are exported, since a silent overwrite would hand
Terraform the wrong identity under a plausible-looking name.

All state lives under ~/.config/ai-sbx; repositories supply nothing and need
no mise.toml.
2026-07-30 13:52:57 -05:00