Platform

Platform overviewArchitectureWorkflow orchestrationGitOps configurationGovernance and AAAAI and MCPKnowledge and contextRuntime and executionEvidence and monitoring

Use cases

All use casesProduction incidentRelease preparationHotfix to productionSecurity scan triage
Why NopsAIIntegrationsSecurity

Resources

All resourcesAI agent governanceMCP governanceMCP securitySelf-hosted platforms
PricingGitHub

Company

How a run worksAboutContactBook a demo

GitHub App and installations

One GitHub App per NopsAI installation, installed on as many organizations and personal accounts as you need.

How-toAdministratorSecurityDeveloper

Key points

  • There is exactly one GitHub App per NopsAI installation. It is installed on any number of accounts, and each installation grants the repositories chosen on GitHub.
  • NopsAI creates the App from a manifest and stores the App ID, private key, and webhook secret itself. Nobody copies a key by hand.
  • The App is created public, because GitHub only lets an account other than the owner install an App that is public. Public means installable, not advertised.
  • An installation on the account that owns the App is enabled on sight. Any other account is held as Pending approval and stays inert until an operator approves it.
  • Only the webhook URL has to be reachable from the internet. The redirect and setup URLs are opened in the operator’s own browser, so NopsAI itself can stay private.

Before you start

Account
A GitHub organization you own, or a personal GitHub account
Reachable webhook
A public address in front of git-bot, such as a tunnel or reverse proxy. NopsAI itself does not need to be reachable.
Access
system.update on system:config, which the setup wizard and System > Git Apps both require

Steps

  1. 01

    Start the connect flow

    Use the GitHub step of the first-install wizard, or System > Git Apps on an existing install. Name an organization to create the App there; leave it empty for your personal account. Only a real organization belongs in that field — a personal username is not one, and GitHub answers a 404.

    Verify
    • The browser leaves for GitHub and shows the App creation page pre-filled from the manifest.
  2. 02

    Approve the App on GitHub

    GitHub creates the App and returns you to NopsAI, which exchanges the one-time code for the credentials and stores them. Nothing is typed in by hand.

    Verify
    • The Git Apps card shows a connected App ID and the address GitHub will deliver to.
  3. 03

    Install it and choose repositories

    NopsAI sends you on to the install page, where you pick the account and the repositories the App may see. Repeat this for every additional organization or account.

    Verify
    • The account appears under GitHub accounts with a repository count.
  4. 04

    Approve accounts you did not install yourself

    An installation from an account other than the App owner arrives as Pending approval. Read the account, then use Approve on the row to enable it.

    Important
    • Approving is what makes an installation live. Until then NopsAI reads none of its repositories and runs none of its triggers.
    Verify
    • The row moves from Pending approval to Connected.

How it works

Registration is GitHub’s manifest handshake, in three moves. NopsAI builds the manifest and a single-use state and hands both to the browser, which posts the manifest to GitHub because GitHub accepts manifests only from an operator’s own session. The operator approves the App, and GitHub redirects back with a one-time code. NopsAI exchanges that code at POST /app-manifests/{code}/conversions for the App ID, slug, private key, and webhook secret, writes the two secrets to the credential store, and sends the operator straight on to the install page.

Installing is a separate step from creating, and it is where repository access is granted: the operator picks the account and the repositories on GitHub, and GitHub calls the App’s setup URL with the installation id. NopsAI never trusts that id from the query string — it verifies the installation against GitHub with an App-authenticated call before storing it.

Because the App is public, anyone who reaches its install URL can attach their own account to it. NopsAI therefore decides whether a new installation counts. The account recorded as github_app_owner at registration is trusted on sight; every other account is stored with pending_approval and disabled. A held installation is genuinely inert rather than merely flagged: git-bot skips disabled installations, so no repository is read and no trigger runs for it.

GitHub un-suspending a held installation does not approve it, and an installation an operator has already ruled on keeps that ruling when later events refresh its metadata. When the owning account is unknown and cannot be resolved, every new installation is held: being unable to tell whether an account is trusted is never treated as trusted.

The App lifecycle events installation and installation_repositories are delivered to every App whether or not it subscribes, and GitHub rejects a manifest that lists them. They are therefore absent from the App’s event list and still received, which is what keeps the installation catalog in step when accounts are added, suspended, or removed directly on GitHub.

git-bot re-reads the App ID, private key, and webhook secret from NopsAI on an interval, so connecting or rotating an App takes effect without restarting the container.

Field reference

github_app_idsetting/git-apps/github.yamlstringRequiredNone

The App GitHub issued at registration. One per NopsAI installation.

Example

4671352

Evidence

services/nopsai/git_apps_handlers.go

github_app_slugsetting/git-apps/github.yamlstringOptionalNone

URL name of the App, used to build the install link github.com/apps/{slug}/installations/new.

Example

nopsai-example

Evidence

services/nopsai/git_apps_registration_model.go

github_app_ownersetting/git-apps/github.yamlstringOptionalNone

Account that owns the App. Installations on this account are enabled on sight; every other account is held for approval. Backfilled from GitHub for an App registered before NopsAI recorded one.

Example

nopsai

Security

This is the whole trust decision for a public App. An empty value holds every new installation rather than trusting any.

Evidence

services/nopsai/git_apps_registration_handlers.go

github_webhook_urlsetting/git-apps/github.yamlstringOptionalDerived from public_url

Where GitHub delivers events. The only address GitHub itself fetches, so it has to reach git-bot from the internet. A value with no path gets /webhook appended.

Example

https://your-tunnel.example.com/webhook

Evidence

services/nopsai/git_apps_registration_model.go

github_installations[].installation_idsetting/git-apps/github.yamlstringRequiredNone

Installation GitHub created when the App was installed on an account.

Example

155436772

Evidence

config/config.go

github_installations[].account_loginsetting/git-apps/github.yamlstringOptionalNone

Account the App is installed on. Matched against github_app_owner to decide whether the installation is trusted on sight.

Example

nopsai

Evidence

config/config.go

github_installations[].enabledsetting/git-apps/github.yamlbooleanOptionaltrue

Whether NopsAI uses this installation. git-bot skips disabled installations, so a disabled entry reads no repositories and starts no runs.

Example

true

Evidence

services/git-bot/internal/service/github_resolver.go

github_installations[].pending_approvalsetting/git-apps/github.yamlbooleanOptionalfalse

Set when the installation arrived from an account other than the App owner. It stays disabled until an operator approves it, and GitHub un-suspending it does not clear the flag.

Example

true

Security

This is what stops a stranger who found the public App URL from attaching their organization to your installation.

Evidence

services/nopsai/git_apps_registration_handlers.go

Examples

setting/git-apps/github.yamlyaml
github_app_id: "4671352"
github_app_slug: nopsai-example
github_app_owner: nopsai
github_webhook_url: https://your-tunnel.example.com/webhook
github_private_key_credential_ref: credential://system/github/app-private-key
github_webhook_credential_ref: credential://system/github/webhook-secret
github_installations:
  - installation_id: "155436772"
    account_login: nopsai
    account_type: organization
    enabled: true
  - installation_id: "778899"
    account_login: partner-org
    account_type: organization
    enabled: false
    pending_approval: true
Result

One App, two accounts: the owner is live, the second waits for an operator to approve it.

Limits

Current behavior
  • A private GitHub App can only be installed on the account that owns it, which is why NopsAI creates the App public. An App registered before this, or switched to "Only on this account" in GitHub, is limited to a single account.
  • The App owner is fixed at creation. Moving the App to a different organization is a GitHub-side transfer, not a NopsAI setting.
  • installation and installation_repositories cannot be subscribed to in the manifest. They arrive regardless; asking for them makes the manifest invalid.

Implementation evidence

  • doc/git-apps.md

    Connect flow, approval rules, GitOps schema, and git-bot routing.

  • services/nopsai/git_apps_registration_handlers.go

    Manifest handshake, installation verification, and the approval guard.

  • services/nopsai/git_apps_registration_model.go

    Manifest contents, event and permission set, and webhook URL normalization.

  • config/config.go

    Stored App and installation schema.