Skip to content

docs: describe how GitHub App installations link to Mogplex - #167

Merged
charlesrhoward merged 8 commits into
mainfrom
docs/github-connection-rules
Nov 9, 2026
Merged

charlesrhoward merged 8 commits into
mainfrom
docs/github-connection-rules

Conversation

@charlesrhoward

@charlesrhoward charlesrhoward commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

The GitHub pages described GitHub OAuth as a way to discover and import repositories, and framed the common failure as "the repo is visible through OAuth but not triggerable". That is no longer how a GitHub App deployment works. Repository access comes only from a Mogplex GitHub App installation linked to the user; GitHub sign-in identifies the user and reads org membership, and never grants repository access. No page said who can link an installation, how linking happens, what to do when an org is missing, or what happens when an installation is revoked.

This change rewrites the access model on the GitHub integration page and the Installations overview, and removes the "OAuth visibility" framing everywhere else. The Installations overview is now the single home for the linking rules:

  • who can link an installation (your personal account, or an org where you are an active org owner) and why org members use team-shared repositories instead
  • the three ways an installation gets linked: the install callback (including installs started on GitHub), discovery when you open Settings → Account, and the installation / installation_repositories webhooks
  • what to do when an org you belong to does not appear, including orgs that restrict third-party OAuth apps
  • revoked installations fail closed, with stored workspaces, drafts, and history kept

Other pages link to those sections instead of repeating them. The OAuth only, Install pending, Synced only, and Not covered labels still exist in the app, so they are redefined rather than removed. Self-hosting pages keep the distinction that an OAuth-only deployment without a GitHub App still lists and imports repositories through OAuth, and now state the narrower identity scopes requested when an App is configured. Repository creation wording on the GitHub integration page and Projects now agrees: in an org you must be an org owner with the installation linked, and the Repository creation permission must be accepted.

Pages touched: integrations/github, web/installations (index, coverage-and-triggerability, repo-sync-and-rebinding), web/settings, web/spaces, web/triggers, web/index, web/guides (github-app-coverage, project-workflow, choose-routing-surface, index), quickstart, index, guides (troubleshooting, sandbox-setup-checklist, common-use-cases, index), reference (glossary, security-and-data-handling), self-hosting (github-app, database-and-auth, environment-variables).

The ordering dependency is satisfied. The Installations overview says Mogplex shows a message after the install callback explaining whether the installation was linked or why not. That message shipped in Mogplex/mogplex#722, which is now deployed. The linking rules describe Mogplex/mogplex#719, which is also merged.

This does not touch configure-and-extend/connections-and-mcp.mdx or cli/automation/ci-integration.mdx, which #166 edits.

@vercel

vercel Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
mogplex-docs Ready Ready Preview Nov 9, 2026 11:13am UTC

Request Review

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

Docs-only PR that correctly replaces the stale "OAuth visibility vs App coverage" framing with the installation-linking model, and all four new /web/installations#... anchors resolve to real headings. Two accuracy problems need fixing first: one sentence documents a post-install confirmation message that has not shipped, and the new webhook-linking paragraph in repo-sync-and-rebinding.mdx reads as self-contradictory and breaks the surrounding bullet list.

4 findings were added inline.

View check run

owns the account. A repository admin who adds one repository is not linked.

It can:
After the install callback, Mogplex shows a message that says whether the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Documents a post-install confirmation message that has not shipped yet

The page now states: "After the install callback, Mogplex shows a message that says whether the installation was linked, or why it was not." Per the PR description, that message ships in a pending Mogplex PR, not in the app this docs release will be published against. Readers will finish an install, look for a confirmation message that does not exist, and conclude the linking failed — exactly the confusion this page is meant to remove.

Either hold this sentence until the app change merges, or land the two together and note the dependency in the PR description so the release order is explicit.

- `installation_repositories` events when repos are added to or removed from an
installation

Only `installation` events for `created`, `new_permissions_accepted`, and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: New webhook-linking paragraph contradicts itself and splits the bullet list

Two problems in the inserted block:

  1. Structure: the paragraph is inserted between list items, so - repository events such as create, rename, transfer, visibility changes, and delete is detached from "The important webhook-backed update paths are:" and renders as a second, separate list. The reader loses the framing sentence for the repository item.
  2. Logic: it says "installation_repositories events for added … link an installation" and then, in the next sentence, "A repository admin who adds one repo to an installation is not linked to it." As written the second sentence simply negates the first. The discriminator is the ownership condition spelled out in web/installations/index.mdx ("links the installation to the Mogplex user who made the change, if that user owns the account"); that condition is missing here.

Suggestion: move the paragraph out of the list (after the full bullet list) and state the rule as "… link an installation to the user who made the change, when that user owns the account. A repository admin who adds one repo to an org installation is not the owner, so that event does not link it."


With a GitHub App, once an installation is linked to you, Mogplex lists only
repos covered by a linked installation, so listed repos are `Trigger-ready`.
`Synced only` appears in a self-hosted deployment without a GitHub App, or for

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Not covered now has two competing definitions, and the symptoms list still shows rows the page says are hidden

The label table above defines Not covered as "The App is installed somewhere for the user, but not for this repo's owner or scope", while the new paragraph redefines it as "an older repo row whose owner has no installation linked to you" — a different condition (owner coverage vs. linkage to you). The same paragraph also says Mogplex hides those rows from the repo list, yet the Typical failure symptoms section on this page still lists "the repo you care about is still Synced only or Not covered" as something a user will observe. A reader cannot tell whether these labels are visible, when, or which definition applies.

Pick one definition for Not covered and make the symptoms list match the visibility rule (for example, drop the Not covered half of that symptom, or state that it applies to older rows surfaced through Support/legacy views).

repo discovery
- **GitHub App installation** gives Mogplex webhook-backed coverage for the
installed account or org
Linking gives you the installation's whole repository set. That set can include

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Team-shared repositories become a primary path with no instructions for using them

"team-shared repositories" is now the documented fallback for every non-owner org member across several pages (integrations/github.mdx, web/guides/github-app-coverage.mdx, web/guides/project-workflow.mdx, reference/glossary.mdx), and web/installations/index.mdx tells those users to "ask an owner to … share the repositories you need with your Mogplex team". No page in this PR — and every existing link points only at "Who can link an installation", which explains the concept rather than the action — says where in the product a teammate shares a repo to a team, or what the receiving member then needs to do to see it.

Add the short how-to here (which surface, who is allowed to share, what the member sees afterwards), or link to the page that documents repo sharing if one exists.

@charlesrhoward

Copy link
Copy Markdown
Contributor Author

Both warnings are fixed in 8dd5441. The sentence about the post-install message stays: it ships in Mogplex/mogplex#722, and the description now says to merge this only after #722 is deployed. In repo-sync-and-rebinding, the webhook-linking paragraph now sits after the full list, so the repository events bullet keeps its intro sentence. The paragraph now states the ownership condition, so the repository-admin case follows from it instead of contradicting it.

I took the Not covered suggestion too. The label table now has one definition (an installation is linked to you, but none of your linked installations covers this repo). It says Mogplex hides those rows from the repo list. The symptom that named the label now describes the repo as missing from Projects.

I left the team-sharing how-to out of this PR. No docs page covers how a repository is shared to a team, and I did not want to name a sharing control without confirming it in the product. That belongs in a follow-up that documents team repository sharing on its own page. The installation pages can then link to it.

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

The access-model rewrite is accurate and the new anchors/links resolve correctly, but the PR leaves the old "repo is visible but not triggerable" model in place on several of the same pages, so the docs now contradict themselves (most visibly web/index.mdx, web/guides/project-workflow.mdx, web/settings.mdx, guides/troubleshooting.mdx). Needs the leftover wording fixed before merge.

2 findings were added inline.

Suggestions

  • Three more places still describe visibility as separate from coverage
    Same model mismatch, smaller blast radius, worth a single sweep in this PR since they are all in pages it already touches:

    • content/docs/web/settings.mdx, "GitHub App coverage details": "Can Mogplex merely see this repo, or is it actually covered for App-backed work?" — and that is the second "fastest way to answer" claim now that web/installations/index.mdx says the Settings → Account question is "Is the App installed on the right owner, and is that installation linked to me?"
    • content/docs/web/settings.mdx, "Fast troubleshooting map": "The repo is visible, but webhook-backed work still does not fire: visibility and App-backed coverage are different states."
    • content/docs/guides/troubleshooting.mdx: the table row "Repo is visible but GitHub events do not fire" and the section "## Repo is visible but events do not fire", which opens with "Visibility and triggerability are different."
    • content/docs/web/guides/choose-routing-surface.mdx and content/docs/web/installations/repo-sync-and-rebinding.mdx ("confirm the repo is App-covered, not just visible") say the same thing in one line each.

    For hosted App deployments the visible-but-uncovered state no longer exists, so "repo missing from Projects" or "route bound to the wrong installation" is the accurate symptom to document.

  • Org membership credential is described differently on product vs self-hosting pages
    content/docs/web/installations/coverage-and-triggerability.mdx and integrations/github.mdx both say GitHub sign-in "identifies you and reads your org memberships". content/docs/self-hosting/database-and-auth.mdx says the opposite for self-hosted deployments: "GitHub sign-in is identity only" (AUTH_GITHUB_*), with membership coming from the separate GitHub OAuth app (GITHUB_CLIENT_*) that also drives installation discovery.

    Was the product-page phrasing intentional? If so, one sentence in the self-hosting pages naming which credential reads org membership (and that the product pages mean the GitHub connection, not the identity provider) would remove the apparent contradiction for self-hosters picking which OAuth apps to register.

  • Not covered label is documented as unreachable (content/docs/web/installations/coverage-and-triggerability.mdx)
    The label table defines Not covered as "An installation is linked to you, but none of your linked installations covers this repo", and the next paragraph says "With a GitHub App, Mogplex hides Not covered rows from the repo list." As written the docs define a state the reader is then told they will never see.

    Suggestion: add where it can still surface (for example in Triggers/Automations installation pickers, or on legacy rows before the first installation-backed sync), or drop the table row.

View check run

Comment thread content/docs/web/index.mdx Outdated
GitHub App installation is linked to you for the owner that holds the repo.
Check [Installations](/web/installations).
- **Why can I see repos but not launch the kind of work I want?** Repo sync and
webhook coverage are separate concerns. Projects can show synced repos before

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Stale "synced but not triggerable" framing survives directly under the rewritten bullet

content/docs/web/index.mdx lines 150-152 (the FAQ bullet right after the bullet this PR rewords): "Why can I see repos but not launch the kind of work I want? Repo sync and webhook coverage are separate concerns. Projects can show synced repos before they are fully triggerable."

Why it matters: the new model says the opposite. project-workflow.mdx now states "Once installation-backed sync is active, Projects lists only repos covered by a linked installation, which hides stale OAuth-only rows", and web/installations/repo-sync-and-rebinding.mdx says "An installation with no repos never brings back the old OAuth-only rows." A reader landing on this FAQ is told a repo can sit in Projects uncovered, which the rest of the docs says cannot happen with an App deployment. The same sentence is exactly the "OAuth visibility" framing the PR description says it removes.

Suggestion: reframe it as a missing-coverage symptom, e.g. "Why is a repo missing from Projects, or why do Triggers not fire for it? The repo owner's installation is not linked to you (or your team has not shared the repo). Fix App coverage first." Keep the visible-but-unroutable wording only for self-hosted OAuth-only deployments and legacy rows, where it is still true.

App install is finished.
- Once installation-backed sync is active, covered repos become the preferred
source of truth in Projects, which helps avoid stale OAuth-only duplicates.
- Repo import needs a linked installation. GitHub sign-in alone does not

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Section 7 of the project workflow contradicts section 4 of the same page

The new bullet at ~line 91 says "Once installation-backed sync is active, Projects lists only repos covered by a linked installation, which hides stale OAuth-only rows." But section 7, ~lines 137-141, still says "For webhook-backed routing, make sure the repo is App-covered, not just synced" and "That is the most common setup miss when a repo looks available in Projects but still will not wake Triggers or Automations."

Why it matters: a page that first tells the reader Projects cannot show uncovered repos then tells them the most common bug is an uncovered repo showing in Projects is self-contradictory. The real remaining failure mode in that section is route scoping (the trigger/automation is bound to a different installation) or a stale binding, which repo-sync-and-rebinding.mdx already describes.

Suggestion: reword section 7 to point at the actual remaining causes, e.g. "Confirm the route is bound to the installation or repo that owns the event. A repo can be covered while the route points at a different installation, or at a stale installation id."

@charlesrhoward

Copy link
Copy Markdown
Contributor Author

Both warnings and the suggestions are addressed in the latest push. The "repos are visible but not triggerable" framing is gone from hosted pages. The web/index FAQ, the Settings troubleshooting map and the Settings installation summary now describe a missing repo as an installation that is not linked to you, as do the troubleshooting table and section, support, the configure-and-extend index, the platform overview and the glossary. Where a listed repo still does not fire, they point at the route's installation binding. Section 7 of the project workflow now names the real remaining cause: a route bound to a different or stale installation id. It links to Repo Sync and Rebinding. The one-line "not just visible" and "not just synced" mentions in repo-sync-and-rebinding and choose-routing-surface are reworded the same way.

The coverage page drops the Not covered row and says instead that Mogplex hides repos none of your linked installations covers. The database-and-auth self-hosting page now says org membership comes from the GitHub connection through the separate OAuth app (GITHUB_CLIENT_*), not from sign-in. That resolves the apparent conflict with the product pages. The troubleshooting heading changed, and no page linked to its old anchor. Mogplex/mogplex#722 is deployed, so the description now marks the ordering dependency as satisfied.

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

Docs-only rewrite of the GitHub access model is accurate, well-structured, and internally consistent on the main points (anchors resolve, PR #719/#722 behaviors are described consistently across integrations, settings, projects, glossary and self-hosting pages). Two wording-level inconsistencies are worth a one-line fix each: the removed Not covered repo label is no longer documented even though the description says the app still renders it, and the Requirements section of the Triggers page still uses the old "synced but not webhook-covered" framing.

3 findings were added inline.

Warnings

  • Triggers page still uses the removed "synced but not webhook-covered" framing
    In the Requirements section of content/docs/web/triggers.mdx, three lines below the new paragraph ("Triggers only work for repos covered by an installed GitHub App... GitHub sign-in on its own is not enough"), the page still says:

    "The creation form searches installations by both account scope and synced repos, so this page is often the fastest way to notice that repos are synced but still not webhook-covered."

    Why it matters: this is exactly the framing the PR sets out to remove, and it contradicts both the paragraph above it and the new claim on the coverage page that a listed repo is Trigger-ready. A reader hitting an empty Triggers page is told two different stories about why.

    Suggestion: restate it in the new model, e.g. "The creation form searches installations by account scope and synced repos, so an empty installation list here usually means the repo owner's installation is not linked to you yet." If a genuinely synced-but-uncovered state still exists (legacy rows, missing webhook permissions), name that state explicitly instead of reusing the old wording.

Suggestions

  • Routing-surface page repeats the "a listed repo may not be covered" caveat the PR just tightened elsewhere
    content/docs/web/guides/choose-routing-surface.mdx still says in "What people usually get wrong": "A repo appearing in Projects does not guarantee it can back a Trigger or Automation. App coverage still has to exist." The PR updated the equivalent statement in repo-sync-and-rebinding.mdx to the new model ("With a GitHub App, a listed repo is covered by an installation linked to you"), so the two pages now disagree in tone.

    Suggestion: mirror the repo-sync-and-rebinding wording and scope the caveat to legacy OAuth-era rows and self-hosted deployments without an App.

View check run

@@ -65,8 +63,14 @@ Each repo effectively falls into one of these buckets:
| Repo label | Meaning |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Not covered repo label is dropped from the docs but still exists in the app

The repo-level coverage table now defines only Trigger-ready and Synced only; the previous Not covered row and the Not covered mention in the failure-symptoms list were both removed. The PR description states the opposite intent: "The OAuth only, Install pending, Synced only, and Not covered labels still exist in the app, so they are redefined rather than removed."

Why it matters: if the app still renders Not covered on legacy or OAuth-era repo rows, a user who sees that label now has no page that explains it, and the two other label tables in the docs (Coverage and Triggerability and Project Workflow) also stop accounting for it. If the label really is unreachable with a GitHub App, saying so in the paragraph under the table would close the loop.

Suggestion: either restore a Not covered row and describe when it can still appear (legacy rows, self-hosted without an App), or add a sentence to the paragraph explaining that Not covered no longer surfaces for App-backed repos. Was dropping it intentional?

| --- | --- |
| `OAuth only` | GitHub is connected, but routing still needs App coverage |
| `Install pending` | The App install was started, but GitHub still needs to finish it |
| `OAuth only` | GitHub sign-in is connected, but no installation is linked to you. You have no repository access of your own yet. In a self-hosted deployment without a GitHub App, this is the normal connected state. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: OAuth only row contradicts the self-hosted exception on the same page

The OAuth only row says "You have no repository access of your own yet" and then, in the same cell, "In a self-hosted deployment without a GitHub App, this is the normal connected state." The page's own ## Sign-in is not enough section says the opposite for that deployment: "there, GitHub OAuth lists and imports repositories."

Suggestion: split the cell so the hosted semantics and the self-hosted exception are stated separately, e.g. "No repository access of your own. A self-hosted deployment without a GitHub App is the exception: there OAuth only is the normal state and OAuth lists and imports repos."

| `Not covered` | The App is installed somewhere for the user, but not for this repo's owner or scope |
| `Synced only` | The repo is in Projects, but has no App coverage |

With a GitHub App, once an installation is linked to you, Mogplex lists only

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Duplicated clause in the repo-label explanation

The paragraph under the repo table says "With a GitHub App, once an installation is linked to you, Mogplex lists only repos covered by a linked installation, so listed repos are Trigger-ready" and then closes with the same setup phrase again: "With a GitHub App, once an installation is linked to you, Mogplex hides repos that none of your linked installations covers."

The two sentences state the same rule twice with the same opening clause. Suggest collapsing to one statement plus the Synced only exception.

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

The rewrite of the GitHub access model is clear and the cross-page structure (linking rules in the Installations overview, other pages deep-linking to those headings) holds up, with all four anchor targets verified. One substantive gap: the repo-level coverage model in Coverage and Triggerability still assumes every visible repo is covered by an installation linked to you, which contradicts the team-shared-repository path this same PR adds on three other pages. A short paragraph fix plus two small wording cleanups make this mergeable.

3 findings were added inline.

View check run

@@ -1,31 +1,29 @@
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Repo-level coverage model has no place for team-shared repositories, and contradicts its own label table

In the ### Repo-level coverage state section, the paragraph after the label table says: "With a GitHub App, once an installation is linked to you, the Projects list shows only repos covered by a linked installation, so listed repos are Trigger-ready. Repos that no linked installation covers are hidden from the list. You see them as Not covered only when you open one directly or show hidden repos."

That leaves no room for team-shared repositories, which this PR introduces as a first-class way to reach a repo:

  • integrations/github.mdx, Repository access table: "GitHub connected, no installation linked | No repositories, except repositories shared to your Mogplex team"
  • web/installations/index.mdx, Sign-in and installations do different jobs: "You can use a repo only when it belongs to an installation linked to you, or when it is shared to your Mogplex team."
  • web/installations/repo-sync-and-rebinding.mdx, Why this matters for Projects: "Team members use those repos without linking their own installation."

The same page also contradicts itself. Synced only is defined as "The repo is in Projects, but has no App coverage and no installation is linked to you" — a state the paragraph says cannot be visible — and then Synced only is restricted to "a self-hosted deployment without a GitHub App, or for older repo rows". A non-owner org member, exactly the reader this PR is trying to unblock, gets opposite answers depending on which GitHub page they land on.

Suggestion: add a clause to the repo-level model for team-shared repos (listed in Projects, covered by the sharing teammate's installation, usable for team work without linking anything themselves) and narrow the "hidden from the list" sentence to repos that are neither linked to you nor shared to your team. Adjust the Synced only sentence so it does not read as "self-hosted or legacy only".

the repo owner
2. Check [Projects](/web/spaces) to confirm the repo is App-covered, not just
visible
2. Check [Projects](/web/spaces) to confirm the repo is listed. With a GitHub

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Troubleshooting step contradicts the team-sharing paragraph on the same page

## Good troubleshooting order, step 2 reads: "Check Projects to confirm the repo is listed. With a GitHub App, a listed repo is covered by an installation linked to you". That is not true for the team-shared repos described earlier on the same page ("Each team-shared repo is checked against the installation of the teammate who shared it. Team members use those repos without linking their own installation").

Suggestion: "a listed repo is covered by an installation linked to you, or by the installation of the teammate who shared it" — otherwise a member who can see the repo is pushed to conclude the installation is missing.

@@ -1,31 +1,29 @@
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: "show hidden repos" names a control the Projects page does not document

The repo-level coverage paragraph says uncovered repos surface "only when you open one directly or show hidden repos". web/spaces.mdx documents a Show removed control for removed (restorable) repos, which is a different state from a repo that lacks installation coverage, and no other page describes a hidden/uncovered-repo toggle. Was "show hidden repos" meant to be that same control? If the Projects surface really has a separate toggle for uncovered repos, naming it exactly (or documenting it on Projects) would let readers find it; if not, dropping the clause is safer than sending people looking for a control that may not exist.

@charlesrhoward

Copy link
Copy Markdown
Contributor Author

Addressed the review in the latest push.

  • Repo-level coverage now covers team-shared repos. Trigger-ready means the repo has an installation id, either from your own installation or from the installation of the teammate who shared it. The page now says what Projects lists in each case, and Synced only is no longer described as self-hosted or legacy only.
  • The coverage labels are API fields (github_coverage_label on /api/repos) and no component renders them. The page now says Projects uses them only to decide what to list. I dropped the "show hidden repos" clause, since no such control exists for uncovered repos (Show removed is for removed repos).
  • repo-sync-and-rebinding.mdx step 2 now includes the sharing teammate's installation. I also pointed troubleshooting step 3 at the coverage section instead of telling readers to look for a label in Projects.
  • I merged main into the branch.

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

Docs-only rewrite of the GitHub access model that reads well and fixes a real gap, but it needs one consistency pass before publish: it states two different sources of org membership (GitHub sign-in vs the GitHub connection OAuth app) and leaves the non-owner/team-shared repository path incomplete.

Warnings

  • Org membership is attributed to GitHub sign-in on web pages, but to the GitHub connection OAuth app on self-hosting pages (content/docs/web/installations/index.mdx:L1)
    The web pages now state the access model as "GitHub sign-in (GitHub OAuth) identifies you and reads your org memberships. It never grants repository access when Mogplex uses a GitHub App." The same sentence appears in content/docs/web/settings.mdx, content/docs/integrations/github.mdx ("GitHub sign-in identifies you and reads your org memberships") and content/docs/web/guides/github-app-coverage.mdx ("GitHub sign-in gives Mogplex your user identity and your org memberships").

    Two self-hosting pages in this same PR say the opposite about which component supplies org membership:

    • content/docs/self-hosting/database-and-auth.mdx: "GitHub sign-in is identity only. Org membership, which Mogplex uses to find and link installations, comes from the GitHub connection through the separate GitHub OAuth app (GITHUB_CLIENT_*)."
    • content/docs/self-hosting/github-app.mdx: the GITHUB_CLIENT_* OAuth app unlocks "User identity and org membership, used to find and link installations", and AUTH_GITHUB_* "is a third, identity-only setting".

    The read:org scope is documented as being requested on the GITHUB_CLIENT_* app, which supports the self-hosting wording. So the "sign-in reads org memberships" phrasing on the web pages conflates two flows.

    Why it matters: the whole point of this PR is that readers learn exactly which GitHub grant does what, and the org-missing troubleshooting path depends on it. A self-hoster debugging a missing org could go check their AUTH_GITHUB_* scopes and find nothing wrong, because the membership read comes from GITHUB_CLIENT_*.

    Suggestion: pick one vocabulary and use it everywhere. Either say "the GitHub connection (GitHub OAuth)" reads org memberships, keeping sign-in strictly identity-only, or add a short clause where the two are the same grant: for example "GitHub sign-in and the GitHub connection are usually the same OAuth grant, and that grant reads your org memberships." If intentional that hosted sign-in and connection share a token while self-hosted deployments may split them, a one-line note on the Installations overview would be worth adding.

  • Team-shared repositories are introduced but the non-owner path through Triggers/Automations is never stated (content/docs/web/triggers.mdx:L1)
    The PR introduces the rule that org members who are not owners do not link the org installation and instead "use team-shared repositories" (content/docs/web/installations/index.mdx, content/docs/web/guides/github-app-coverage.mdx, content/docs/web/installations/coverage-and-triggerability.mdx). content/docs/web/triggers.mdx still resolves an empty Triggers page with: "confirm the correct user or org has the Mogplex GitHub App installed and the installation is linked to you".

    For a non-owner org member that instruction is a dead end: they cannot link the installation, and no page says whether hosted routes may be created against a teammate's installation for a team-shared repo. Since the Installations overview is presented as the single home for the linking rules, this is the one case the rules do not cover.

    The absolutes elsewhere make the same gap visible: content/docs/integrations/github.mdx opens with "Repository access comes only from a Mogplex GitHub App installation that is linked to you", while the access table on that page has a "GitHub connected, no installation linked" row whose answer is "No repositories, except repositories shared to your Mogplex team". content/docs/web/installations/index.mdx keeps the nuance ("...linked to you, or when it is shared to your Mogplex team") but the "only ... linked to you" phrasing does not.

    Suggestion: add one sentence to "Who can link an installation" stating what a non-owner member can and cannot do with a team-shared repo (specifically whether Triggers and Automations can target the team's installation), and soften the "only" sentences to "...or repositories a teammate has shared to your Mogplex team". If team-shared repos are deliberately not triggerable for those members, say so explicitly in web/triggers.mdx so the troubleshooting advice does not send them in circles.

Suggestions

  • The "unless none of your repos has one" fallback contradicts the bullet above it (content/docs/web/installations/coverage-and-triggerability.mdx:L1)
    The "What Projects lists" bullets read: "Once an installation is linked to you, Projects lists only repos that have an installation id, even if you also have synced repos without one." followed by "Repos without one stay out of the list, unless none of your repos has one." The exception makes the preceding "only" untrue as written, and it is unclear when it applies (no GitHub App configured? first sync? a transient state?).

    Suggestion: state the exception on its own terms instead of as a trailing clause, for example: "In a deployment with no GitHub App, or before any of your repos has an installation id, Projects falls back to the synced list so it is not empty." That keeps the default rule unambiguous and names the condition.

  • "Account sync" wording survives where visibility is now defined by installations (content/docs/reference/glossary.mdx:L1)
    The glossary entry's body now says visibility comes from an installation linked to you or shared to your team, but its lead line still defines it as "Whether Mogplex can see a repo through account sync." content/docs/guides/troubleshooting.mdx keeps the same phrase in the first-split table: "Repo is missing or stale | installation not linked to you, account sync, or Projects".

    Since this PR removes the OAuth-visibility framing everywhere else, these two leftovers are the only places still attributing visibility to "account sync".

    Suggestion: align the glossary lead line with the new body, and replace "account sync" in the troubleshooting row with the surface the reader can actually open (for example "installation not linked to you, Synced only state, or Settings → Repositories").

View check run

@charlesrhoward

Copy link
Copy Markdown
Contributor Author

Addressed the third review in one push, after checking both warnings against Mogplex/mogplex main.

  • Org membership source. Better Auth's GitHub sign-in (AUTH_GITHUB_*) uses default scopes and stores no token. Org membership comes from the GitHub connection (/api/auth/github, GITHUB_CLIENT_ID, read:org). The web pages now say "the GitHub connection (GitHub OAuth)" reads org memberships, and that signing in with GitHub only identifies you. This matches the self-hosting pages.
  • Member path for triggers and automations. POST /api/triggers and validateFlowConfiguration both require a github_installations row for the acting user. A member can work on team-shared repos but cannot create triggers or automations for them. The Installations overview and Triggers now say so, and point to an org owner who has linked the installation. I also softened the "only" sentence in integrations/github.mdx.
  • Fallback when no repo has an installation id. This is now its own sentence with the condition named.
  • Leftover "account sync" wording. Removed from the glossary lead line and the troubleshooting table.

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

Approve-ready: the new access model is consistent with integrations/github, the glossary, and the self-hosting pages, and every anchor invented by the rewrite (#who-can-link-an-installation, #how-an-installation-gets-linked, #an-org-you-belong-to-does-not-appear) resolves. One table cell in the page that now owns the label definitions contradicts itself for self-hosted readers, plus a few cross-page wording slips worth fixing.

Warnings

  • The OAuth only row contradicts itself for self-hosted deployments (content/docs/web/installations/coverage-and-triggerability.mdx:L32)
    The row reads "GitHub sign-in is connected, but no installation is linked to you. You have no repository access of your own yet. In a self-hosted deployment without a GitHub App, this is the normal connected state."

    The first sentence is false in exactly the configuration the third sentence calls normal. In a self-hosted deployment without a GitHub App, the OAuth connection does list and import repositories: self-hosting/github-app.mdx says the OAuth app is granted repo "so it can list and import repositories" when no App is configured, self-hosting/database-and-auth.mdx says "A deployment without a GitHub App lists repositories through a separate GitHub OAuth app instead", and reference/glossary.mdx says only that configuration lists repos through GitHub OAuth.

    Read as written, a self-hoster who can see their repos is told they have no repository access. Split the meaning: "In a hosted deployment that is no repository access of your own yet. In a self-hosted deployment without a GitHub App, this is the normal connected state and repos are listed through OAuth, but none of them can start hosted GitHub-event work."

Suggestions

  • The setup-state table says OAuth-only never unlocks repo import (content/docs/web/guides/project-workflow.mdx:L35)
    The OAuth only row lists "Your own repo import" under What it does not unlock yet, with no self-hosted qualifier. That is the hosted rule, and it contradicts integrations/github.mdx and reference/glossary.mdx, which both keep the exception that an OAuth-only self-hosted deployment still lists and imports repositories.

    Since this table is the short version readers will copy, one clause after it ("In a self-hosted deployment without a GitHub App, OAuth only still imports repos through OAuth; they still cannot trigger App-backed work.") keeps it aligned with the rest of the rewrite.

  • Webhook linking wording is broader than the linking rules (content/docs/web/installations/coverage-and-triggerability.mdx)
    In "Discovery can fill in missing installation state": "A GitHub webhook can also link an installation when you install the App or add repositories to it."

    The authoritative section it links to is narrower: web/installations/index.mdx says the webhook links the installation only "if that user owns the account", and "A repository admin who adds one repository is not linked." As written here, a non-owner repo admin would expect adding a repo to link the installation for them.

    Suggest "…when you install the App or, as an account or org owner, add repositories to it" so the pointer and the target say the same thing.

  • "Open Installations" points at a route the overview says does not exist (content/docs/self-hosting/github-app.mdx)
    Step 3 of "Install and verify" says "Open Installations and confirm coverage", and the same phrasing appears in web/installations/coverage-and-triggerability.mdx (troubleshooting step 2) and integrations/github.mdx (where to check state). But the page they land on opens with "There is not a separate top-level /installations dashboard route today" and says the state is surfaced in Settings → Account.

    A reader follows "Open Installations", lands on a doc page, and has no product route to open. Reword to something like "Check the linked installations under Settings → Account (see Installations)", so the link is presented as further reading rather than a destination.

  • "stale OAuth-only rows" mixes the two label vocabularies (content/docs/web/guides/project-workflow.mdx)
    "Once installation-backed sync is active, Projects lists only repos covered by a linked installation, which hides stale OAuth-only rows."

    OAuth only is the user-level connection state; the repo-level state this sentence is describing is Synced only ("the repo has no installation id"), per the redefined labels in web/installations/coverage-and-triggerability.mdx. Since this PR's whole point is that the labels keep distinct meanings, say "hides stale Synced only rows".

View check run

@charlesrhoward

Copy link
Copy Markdown
Contributor Author

The review marked this approve-ready. The last push fixes its one warning and all four suggestions.

  • The OAuth only row now treats the hosted and self-hosted cases separately. Self-hosted without an App lists and imports repos through OAuth, but those repos cannot start hosted GitHub-event work.
  • project-workflow.mdx has a matching self-hosted note under the setup-state table, and now says "stale Synced only rows".
  • The webhook linking sentence is now limited to the account or org owner.
  • "Open Installations" in three places now points to Settings → Account, with the Installations page linked for reference.

Auto-merge (squash) is enabled.

@charlesrhoward
charlesrhoward enabled auto-merge (squash) November 9, 2026 11:13
@charlesrhoward
charlesrhoward merged commit 36e3568 into main Nov 9, 2026
7 checks passed
@charlesrhoward
charlesrhoward deleted the docs/github-connection-rules branch November 9, 2026 11:14

@mogplex mogplex Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mogplex PR Review

Status: Attention needed

The rewrite of the GitHub access model is accurate and internally consistent on the big points (linking rules, callback/discovery/webhook paths, revocation, the self-hosted OAuth-only exception), and every new anchor I checked resolves to an existing heading — but two pages make incompatible claims about whether stale OAuth-only repo rows reappear in Projects, which should be resolved before merge. Remaining items are naming and wording polish.

2 findings were added inline.

Suggestions

  • Two first-run checklists still phrase App coverage as something to confirm rather than install (content/docs/index.mdx)
    The new model says repository access exists only after someone installs the App on the owner and the installation is linked to the user, but two first-run lists still read as if coverage might already be there:

    • content/docs/index.mdx, "The shortest reliable first-day path" step 2: "Confirm the right user or org has Mogplex GitHub App coverage in Installations." — step 1 only says connect GitHub, so a brand-new account has nothing to confirm.
    • content/docs/web/spaces.mdx, "A practical first workflow" step 2: same wording.

    Rewording both to an action plus a check ("Install the Mogplex GitHub App on the owner — for an org, an org owner does this — then confirm the installation is linked to you in Installations") matches the setup order on github.mdx and web/settings.mdx and keeps the removal of the OAuth-visibility framing complete.

  • Confirm the "Installed scopes" label exists on Settings → Account (content/docs/web/installations/index.mdx)
    web/installations/index.mdx now states that Settings → Account "shows each linked installation under Installed scopes", with an install summary above it. web/settings.mdx describes the same block twice without ever using that heading ("GitHub App coverage and synced repo counts", "The GitHub App coverage block shows more than a binary yes/no").

    If the Account page really has an "Installed scopes" heading this is fine and settings.mdx could adopt the term; if it does not, the bolded label sends readers looking for a section that isn't there. Worth a quick check against the deployed app, since this is the exact block the new "org does not appear" troubleshooting tells people to inspect.

  • No automated check for the new in-page anchors (content/docs/web/installations/index.mdx)
    This change adds six /web/installations#... anchor links (from integrations/github.mdx, web/settings.mdx, web/guides/github-app-coverage.mdx, web/guides/project-workflow.mdx) whose targets are headings that this same PR creates or keeps. I checked all of them against the head revision and they resolve today, but nothing in CI would catch a later heading rename: the only tests are execution-environments-docs.test.mjs and legacy-api-redirect.test.mjs.

    A small addition to the existing node --test suite that walks content/docs/**/*.mdx, collects ](/path#anchor) links, and asserts each target page and heading slug exists would have caught this class of breakage for free.

View check run

an installation is linked to you, Projects lists only repos that have an
installation id, whether it comes from your own installation or from the
teammate who shared the repo. Repos without one stay out of the list.
If none of your repos has an installation id yet, for example before the first

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning: Coverage page and repo-sync page disagree about whether stale OAuth-only rows reappear in Projects

coverage-and-triggerability.mdx:70-77 says that once an installation is linked, Projects lists only repos that have an installation id, then adds a fallback: "If none of your repos has an installation id yet, for example before the first sync after an install, Projects shows all your repos so the list is not empty."

repo-sync-and-rebinding.mdx:53-60 ("Why this matters for Projects") states the opposite for the same window: "Once an installation is linked to you, the repo inventory includes only repos the linked installations currently grant. Repos left over from an earlier OAuth sync ... are excluded. ... An installation with no repos never brings back the old OAuth-only rows."

In the "installation linked, first sync not run yet" case both conditions are true at once, so a reader cannot tell whether their old Synced only rows will reappear in the picker. One of the two sentences is inaccurate; the pages should agree. If the fallback really exists, scope it to accounts with no linked installation and drop the "never brings back" promise in repo-sync-and-rebinding.mdx; otherwise remove the fallback sentence.

That distinction matters because Mogplex treats these setup states
differently:

| State | What it unlocks | What it does not unlock yet |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Setup-state names in the project-workflow table do not match the labels defined on the coverage page

This table now uses the canonical app labels for the first two rows (OAuth only, and `Synced only` in the prose below it), but the remaining rows are paraphrases: App install pending, App installed, no synced repos yet, App installed with synced repos. coverage-and-triggerability.mdx:47-57 defines those same states as Install pending, App installed, and Ready.

Since the point of this change is that the labels still exist in the app, a reader comparing this table with Settings will look for App install pending and not find it. Aligning the rows with the canonical names (or stating explicitly that this table lists setup stages rather than app labels) removes the mismatch.

This branch was successfully deployed

1 active deployment
Preview — 82208836 Deployed Nov 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant