Skip to main content
Orbi keeps secrets local, limits protected-branch operations to the Runner, and requires a reviewed PR before merge. Orbi runs an autonomous coding agent with a GitHub token on your machine. The security model is deliberately simple: hard boundaries in the delivery contract, local-only secrets, and no remote state store.

Delivery boundaries

  • GitHub Issues and labels are the only state store; Orbi has no database, message queue, or web UI.
  • The Python Runner is not a daemon: a systemd user timer starts one tick every five minutes, and each tick processes at most one Issue or resumes one opened PR before exiting.
  • Orbi has no task DAG, multi-agent parallelism, risk model, policy engine, or fallback path. Command errors fail fast and leave the scene in the journal and Issue comment.
  • There is no business task timeout: a slow model is not a failure. Command errors, an unavailable environment, or an unresolvable review fail fast.
  • Orbi does not discover repositories, merge or push protected branches itself, or run without a working model endpoint.

The AI never merges or pushes protected branches

  • The implementer Pi stops at the committed delivery: it does not fetch the base, does not push, and does not create the PR — the Runner pushes the task branch (plain push, never force) and opens one PR (Issue #186). The Pi does not merge, does not push main/master, does not force push, and never auto-resolves conflicts.
  • The Runner is the only merge actor, and it merges only through the reviewed PR: a clean REVIEW_VERDICT — read by a backwards scan that tolerates the reviewer’s natural-language wrapping (Issue #774), never adopts a REVIEW_VERDICT mention that is not a verdict line, fails on two conflicting verdicts, and is bound to the reviewed head SHA (Issue #591: a verdict line injected through the Issue body, the diff or a comment never overrides the reviewer’s conclusion, and a verdict naming another head never merges) — the merge gate (PR head contains the latest remote base, PR mergeable, remote head still the reviewed head), and gh pr merge --match-head-commit so exactly the reviewed head lands.
  • GitHub branch protection on the default branch is the final boundary: keep the protected branch restricted to the account that runs the Runner (or to no one — the Runner’s token performs the merge).
  • Delivery state is derived, never trusted from public text: the resume scene is only read from comments posted by a trusted maintainer (OWNER/MAINTAINER/MEMBER/COLLABORATOR), and branch/worktree paths are derived from the configured repo, Issue number and run id — a public comment can never steer the Runner into an arbitrary local path. The machine-readable record is the hidden versioned orbi:scene:v1 block rendered and parsed by src/orbi/scene.py; the readable text beside it is display only.

GitHub token (API) and SSH (git data) — two channels

  • GitHub API operations (Issue, PR, label, comment, merge) authenticate with gh (gh auth status must succeed). Use a fine-grained personal access token scoped to the repositories the Orbi actually works on, with the minimum permissions: contents (read/write), pull requests (read/write), issues (read/write), and metadata (read). Avoid organization-wide or classic broad-scope tokens.
  • Git data operations (fetch, push — including .github/workflows/*.yml) authenticate with the machine’s SSH key over [email protected]:owner/repo.git (Issue #114), or — with git_transport = "https" (Issue #580) — with the gh credential helper over https://github.com/<repo>.git (the token-only sandbox path). A workflow push must never depend on the OAuth App workflow scope — the HTTPS/OAuth transport that blocked Issue #106. The pre-start check verifies the configured transport and fails fast when it is broken (no fallback).
  • The channels are never mixed: SSH is never an API authentication, and the GitHub API never authenticates over SSH. In the default ssh transport mode the gh token is not a git-data credential (the machine’s SSH key is); in https transport mode (Issue #580) the token IS the git-data credential — by explicit configuration, supplied to git by the gh credential helper. The token lives in gh’s local credential store on the Runner machine; the SSH key lives in the user’s SSH agent/config. Neither is written into the repository, the config file, the journal, or a GitHub comment.
  • Logs are redacted by construction: command lines carrying secrets are logged as <redacted>, and tool summaries are truncated and masked. The full prompt, Issue body and token never reach the journal or the progress comments.
  • Rotate the token on a normal schedule; a compromised token is contained to the repositories it can see.

Local state files

Orbi keeps local state that never leaves the machine:
  • Config (orbi.toml): local, gitignored. The repository only ships the packaged example (src/orbi/example_config.toml).
  • Run artifacts: plan, test log, session JSONL and review evidence live in the task worktree (.worktrees/..., gitignored).
  • Slots: <repo_dir>/.orbi/slots/slot-N lock files (gitignored via the .orbi/ directory convention of the checkout).
  • KV cache files (only if you run the optional local-llm-kv-cache proxy): the disk-backed prefix and session KV state (e.g. ~/.llama-slot-cache/*.bin) contains serialized model state derived from your prompts — treat it as sensitive local data, keep it on the same machine, and delete it if you no longer need the cached sessions.
If you run Orbi on a shared machine, give the Runner user its own home directory so the config, worktrees and KV files stay private to that user.

Repository-level config: the trust model

A repository may carry a delivery-policy file at .github/orbi.toml (see Workflow). It is read from the default branch tip at claim time. The trust argument for allowing it is the same one that already applies to CI workflows:
  • A contributor without merge rights cannot land the file on the default branch, so it is out of scope.
  • A maintainer who can merge already controls CI workflows on the default branch — arbitrary code execution plus the repository’s secrets. The marginal risk of a policy key is therefore ≈ 0.
  • Orbi itself can merge its own reviewed output, unlike Dependabot/Renovate. If prompt injection ever crossed the review gate, the worst case for a whitelisted policy key is a visible, reversible policy change — the run comment always records repo_config: <sha> and annotates a change with its effective diff.
The red line is credential routing. Keys that decide where ORBI_GITHUB_TOKEN and the model API keys are sent — pi_provider, pi_model, pi_thinking, pi_providers, pi_extensions, the model_wait_probe_url endpoint and every other endpoint/key field — stay permanently host-only. A deployment host serves several pools (zcode-website / zcode-e2e / production), so one compromised repository config must not be able to redirect all host credentials or move work across pools. For the same reason source_repos/repo_dir/ deploy_home/workspace_root (cross-pool movement) and prompt/prompt_review/skills (a persistent injection channel into the system context) are host-only. A repository file that declares any host-only key fails the claim fast and the Issue becomes ai-blocked with the offending keys named. An unrecognized key is ignored with a warning instead (Issue #1329); the host-only set is unchanged by that. These delivery-policy keys are repository-writable: base_branch, active_milestone, auto_next_milestone, context_files, dispatch_label, steering_enabled, steering_poll_seconds, steering_max_rounds, release_confirmation and clarify_thin_tickets. The steering values affect only that repository; omitted keys fall back to host configuration. Because a policy change is a default-branch change, protect the file with GitHub’s native review mechanism — add .github/orbi.toml to CODEOWNERS so changing it requires an owner’s review.