> ## Documentation Index
> Fetch the complete documentation index at: https://ryvn.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Set up the GitHub App for your dedicated Ryvn hub

> Create the GitHub App your dedicated Ryvn hub uses to talk to your GitHub organization, and hand the generated credentials to Ryvn.

export const GitHubAppForm = () => {
  const CREATE_URL = "https://ryvn.ai/github-app/create";
  const HOSTNAME = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i;
  const GITHUB_LOGIN = /^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){0,38}$/i;
  const [org, setOrg] = useState("");
  const [slug, setSlug] = useState("");
  const [hub, setHub] = useState("");
  const [code, setCode] = useState("");
  const [error, setError] = useState("");
  useEffect(() => {
    const q = new URLSearchParams(window.location.search);
    if (q.get("org")) setOrg(q.get("org"));
    if (q.get("slug")) setSlug(q.get("slug"));
    const c = q.get("code");
    if (c && (/^[A-Za-z0-9_-]+$/).test(c)) setCode(c);
  }, []);
  const host = hub.trim();
  const api = "https://api." + host;
  const validate = () => {
    if (!GITHUB_LOGIN.test(org.trim())) return "Enter the GitHub organization name (as it appears in github.com/<org>).";
    if (!GITHUB_LOGIN.test(slug.trim())) return "Enter a customer slug using letters, digits and single hyphens.";
    if (!HOSTNAME.test(host)) return "Enter the hub domain as a bare hostname, for example acme.ryvn-abc12.ryvn.run.";
    return "";
  };
  const onSubmit = e => {
    e.preventDefault();
    const problem = validate();
    setError(problem);
    if (problem) return;
    const params = new URLSearchParams({
      org: org.trim(),
      slug: slug.trim(),
      hub: host
    });
    window.open(CREATE_URL + "#" + params.toString(), "_blank", "noopener");
  };
  const inputStyle = {
    display: "block",
    width: "100%",
    marginTop: "0.25rem",
    padding: "0.5rem",
    border: "1px solid rgba(128,128,128,0.6)",
    background: "transparent",
    font: "inherit",
    fontSize: "0.875rem"
  };
  const labelStyle = {
    display: "block",
    marginTop: "1rem",
    fontSize: "0.875rem",
    fontWeight: 600
  };
  return <div className="not-prose" style={{
    margin: "1.5rem 0",
    padding: "1.25rem",
    border: "1px solid rgba(128,128,128,0.4)"
  }}>
      <form id="rga-form" onSubmit={onSubmit}>
        <label style={{
    ...labelStyle,
    marginTop: 0
  }} htmlFor="rga-org">
          GitHub organization
        </label>
        <input id="rga-org" style={inputStyle} placeholder="acme" value={org} onChange={e => {
    setOrg(e.target.value);
    setError("");
  }} />
        <label style={labelStyle} htmlFor="rga-slug">
          Customer slug (App is named <code>ryvn-&lt;slug&gt;</code>; must be unique on GitHub)
        </label>
        <input id="rga-slug" style={inputStyle} placeholder="acme" value={slug} onChange={e => {
    setSlug(e.target.value);
    setError("");
  }} />
        <label style={labelStyle} htmlFor="rga-hub">
          Ryvn hub domain (as given to you by Ryvn)
        </label>
        <input id="rga-hub" style={inputStyle} placeholder="acme.ryvn-abc12.ryvn.run" value={hub} onChange={e => {
    setHub(e.target.value);
    setError("");
  }} />
        {host ? <p id="rga-target" style={{
    marginTop: "0.75rem",
    fontSize: "0.8rem"
  }}>
            GitHub will send webhooks and installation callbacks to {api}/ - make sure this is the hub domain Ryvn gave
            you.
          </p> : null}
        <button id="rga-submit" type="submit" style={{
    marginTop: "1.25rem",
    padding: "0.5rem 1rem",
    border: "1px solid currentColor",
    background: "transparent",
    color: "inherit",
    font: "inherit",
    fontSize: "0.875rem",
    fontWeight: 600,
    cursor: "pointer"
  }}>
          Create on GitHub
        </button>
      </form>
      <p style={{
    marginTop: "0.75rem",
    fontSize: "0.8rem"
  }}>
        Opens a review page on ryvn.ai showing the settings that will be applied, then GitHub's Create GitHub App page in your
        organization.
      </p>
      {error ? <p id="rga-error" role="alert" style={{
    marginTop: "0.75rem",
    fontSize: "0.875rem",
    color: "#dc2626"
  }}>
          {error}
        </p> : null}
      {code ? <div style={{
    marginTop: "1rem",
    padding: "0.75rem",
    border: "1px solid #16a34a",
    fontSize: "0.875rem"
  }}>
          <strong>GitHub returned a one-time code.</strong> It expires in one hour; convert it now:
          <pre style={{
    marginTop: "0.5rem",
    overflow: "auto",
    fontSize: "0.75rem"
  }}>
            {'curl -sS -X POST -H "Accept: application/vnd.github+json" \\\n  "https://api.github.com/app-manifests/' + code + '/conversions" > ryvn-github-app.json'}
          </pre>
        </div> : null}
    </div>;
};

Your dedicated Ryvn hub connects to GitHub through a GitHub App that your organization owns. This page creates it with
the settings pre-filled; you review and confirm on GitHub, then send the generated credentials to Ryvn.

<Info>
  You need **owner** permission on the GitHub organization and the **hub domain** Ryvn gave you (for example
  `acme.ryvn-abc12.ryvn.run`). If you are not an organization owner, forward the [manual setup](#set-up-manually)
  section below to someone who is.
</Info>

<Steps>
  <Step title="Create the App">
    Fill in the three fields and click **Create on GitHub**. A review page shows the settings that will be applied;
    click **Create on GitHub** there, and on GitHub's **Register new GitHub App** page click **Create GitHub App for
    \<org>**.

    <GitHubAppForm />

    <Warning>
      Check the hub domain before you create the App. It decides where GitHub sends webhooks and installation callbacks.
      Only use the domain Ryvn gave you directly, never one from an unsolicited link.
    </Warning>
  </Step>

  <Step title="Convert the one-time code into credentials">
    GitHub sends you back to this page with a `code=` parameter in the URL, and the form shows the ready-to-run command
    (valid for **one hour**, no authentication needed):

    ```sh theme={null}
    curl -sS -X POST -H "Accept: application/vnd.github+json" \
      "https://api.github.com/app-manifests/<code>/conversions" > ryvn-github-app.json
    ```

    `ryvn-github-app.json` contains everything the hub needs:

    | Field                         | Used as                               |
    | ----------------------------- | ------------------------------------- |
    | `id`                          | GitHub App ID                         |
    | `slug`                        | App name                              |
    | `client_id` / `client_secret` | OAuth client for the install callback |
    | `webhook_secret`              | webhook signature secret              |
    | `pem`                         | App private key                       |

    <Warning>
      Treat this file as a secret and do not commit it. GitHub never shows the private key again; if you lose the file,
      generate a new private key and client secret from the App's settings page and read the webhook secret from its
      **Webhook** section.
    </Warning>
  </Step>

  <Step title="Hand the credentials to Ryvn">
    Send `ryvn-github-app.json` to your Ryvn contact over the agreed secure channel, never in plain-text email or chat.
    Ryvn configures your hub with it and tells you when it is live.
  </Step>

  <Step title="Install the App from your hub">
    Sign in to your hub at `https://<hub domain>`, open **Settings → Source control** and click **Install GitHub App**.
    Select the repositories Ryvn should manage and confirm.

    <Note>
      Always start the installation from the hub, not from GitHub's App page: an installation started on GitHub is not
      linked to your Ryvn organization. If that happened, uninstall it from the organization's **Installed GitHub Apps**
      page and start again from the hub. You can add repositories later from the installation's settings page on GitHub.
    </Note>
  </Step>
</Steps>

## Set up manually

If you prefer to create the App by hand, or need to forward the requirements to an organization owner, use the settings
below. Replace `<hub>` with your hub domain and `<slug>` with your Ryvn customer slug.

1. Go to `https://github.com/organizations/<org>/settings/apps/new` (**Organization settings → Developer settings →
   GitHub Apps → New GitHub App**).

2. Fill in the form:

   | Field                                                  | Value                                                     |
   | ------------------------------------------------------ | --------------------------------------------------------- |
   | GitHub App name                                        | `ryvn-<slug>`                                             |
   | Homepage URL                                           | `https://ryvn.ai`                                         |
   | Callback URL                                           | `https://api.<hub>/v1/integrations/github/setup-callback` |
   | Request user authorization (OAuth) during installation | on                                                        |
   | Setup URL                                              | `https://api.<hub>/v1/integrations/github/setup-callback` |
   | Redirect on update                                     | on                                                        |
   | Webhook: Active                                        | on                                                        |
   | Webhook URL                                            | `https://api.<hub>/v1/integrations/github/webhook`        |
   | Webhook secret                                         | generate one, e.g. `openssl rand -hex 32`, and keep it    |
   | Where can this GitHub App be installed?                | Only on this account                                      |

3. Set **Repository permissions**:

   | Permission    | Access         |
   | ------------- | -------------- |
   | Actions       | Read-only      |
   | Checks        | Read and write |
   | Contents      | Read and write |
   | Metadata      | Read-only      |
   | Pull requests | Read and write |
   | Workflows     | Read and write |

   and **Organization permissions**: **Members** → Read-only. Leave everything else at *No access*.

4. **Subscribe to events**: `Push` and `Pull request`.

5. Click **Create GitHub App**. On the App's page, note the **App ID** and **Client ID**, click **Generate a new client
   secret**, then scroll to **Private keys** and click **Generate a private key** (downloads a `.pem` file).

6. Send the App name, App ID, Client ID, client secret, webhook secret and the `.pem` file to your Ryvn contact over the
   agreed secure channel. Once Ryvn confirms the hub is configured, continue with **Install the App from your hub**
   above.

## Updating the App later

When a Ryvn release needs additional permissions or events, Ryvn tells you what to change. Open the App's
**Permissions & events** page, apply the change and save, then accept the new permissions on the installation page
(GitHub emails organization owners a link).
