This guide is for a self-hosted Open Mission installation that needs unattended GitHub access.

The ownership split is:

  • browser OAuth login is user-scoped and interactive
  • GitHub App credentials are system-scoped for one Open Mission installation
  • GitHub App installation binding is Repository-scoped authorization for unattended operations

See ADR 0004.05 for the governing rule.

What You Need

  • a GitHub organization or user account that will own the GitHub App
  • admin access to create and install that GitHub App
  • a self-hosted Open Mission installation
  • Node 24 and the open-mission CLI installed locally

1. Create A GitHub App

In GitHub:

  1. Open organization or user settings.
  2. Go to Developer settings.
  3. Choose GitHub Apps.
  4. Select New GitHub App.

Recommended initial settings:

  • App name: a deployment-specific name such as open-mission-acme-local
  • Homepage URL: the local or internal URL used to access your Open Mission web host
  • Callback URL: the Open Mission GitHub OAuth callback URL if you also want browser login through this app
  • Webhook: optional for the first unattended-access wave

Recommended initial repository permissions for unattended Repository delivery:

  • Contents: Read and write
  • Pull requests: Read and write
  • Issues: Read and write if Open Mission will create or update issues
  • Metadata: Read-only

Add only the minimum permissions your installation needs.

2. Collect The App Credentials

From the GitHub App settings page, collect:

  • App ID
  • Client ID
  • Client secret

Then generate and download a private key from the GitHub App settings page.

Important split:

  • GITHUB_APP_PRIVATE_KEY is used by the daemon to mint installation access tokens
  • GITHUB_APP_CLIENT_SECRET is used for user OAuth login through the web host

They are different credentials and are not interchangeable.

3. Install The GitHub App On Repositories Or Organizations

Install the GitHub App on the organization or repositories Open Mission should manage.

This installation step is what gives GitHub an installation id and grants repository access. Open Mission should later bind that installation to specific Repository records for unattended actions.

4. Configure Environment Variables For Open Mission

Provide these variables in the shell, container environment, or service manager that launches Open Mission.

Required for unattended GitHub App installation auth:

export GITHUB_APP_ID="1234567"
export GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----"

Optional but recommended when the same GitHub App also handles browser login:

export GITHUB_APP_CLIENT_ID="Iv1.abcdef1234567890"
export GITHUB_APP_CLIENT_SECRET="your-client-secret"

Optional for webhook verification later:

export GITHUB_APP_WEBHOOK_SECRET="your-webhook-secret"

If you store the private key in a single-line env value, newline escapes are supported:

export GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"

The daemon-side installation token provider in packages/core/src/platforms/GitHubAppTokenProvider.ts reads GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY, generates a GitHub App JWT, exchanges it for an installation access token, and caches that installation token until it is close to expiry.

5. Bind Each Repository To Its GitHub App Installation

After Open Mission is running with the GitHub App environment variables set:

  1. Sign in to Open Mission through GitHub in the browser.
  2. Open or add the Repository you want to authorize for unattended GitHub work.
  3. Invoke the Repository bindGitHubAppInstallation mutation.

Current behavior:

  • the binding discovery uses the signed-in user’s GitHub OAuth token
  • Open Mission discovers which installed GitHub App installation can access that Repository
  • the Repository stores the resulting installation binding as Repository-owned authorization state

This binding is distinct from deployment credentials. The Repository stores only the installation id and related authorization facts, not the GitHub App private key.

At the current implementation stage, this binding step exists at the Repository entity boundary. open-mission install does not perform it for you.

6. Run Open Mission Installation

open-mission install configures local non-secret Open Mission settings such as repository and mission roots.

Run:

open-mission install

or for one-shot startup:

open-mission

What open-mission install does today:

  • ensures Open Mission config exists
  • prompts for repository and mission roots when needed
  • records non-secret config in the Open Mission config file

What it does not do today:

  • create a GitHub App for you
  • upload or persist GitHub App secrets into Open Mission config
  • complete Repository installation binding automatically

7. Verify The Running Installation

Start Open Mission in the same environment where the GitHub App variables are set.

open-mission

For local development with this repository, .env.example shows the supported GitHub App variables in /.env.example.

Current State Of The Implementation

Implemented now:

  • browser login can use GITHUB_APP_CLIENT_ID and GITHUB_APP_CLIENT_SECRET
  • daemon-side GitHub App installation token minting uses GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY
  • Repository-owned installation binding storage and configuration exist
  • Repository bindGitHubAppInstallation can discover and persist the binding from a signed-in GitHub user session
  • unattended Repository reads, writes, and setup pull request automation can run through the stored Repository binding

Not fully implemented yet:

  • a polished operator-facing UI flow for binding and re-binding installations
  • any fully automatic installation-binding step inside open-mission install

So the core Repository authorization flow now exists, but the surrounding operator ergonomics are still a follow-up.