diff --git a/apps/gittensory-ui/src/routes/docs.maintainer-self-hosting.tsx b/apps/gittensory-ui/src/routes/docs.maintainer-self-hosting.tsx index a194c6b712..28aecaaf51 100644 --- a/apps/gittensory-ui/src/routes/docs.maintainer-self-hosting.tsx +++ b/apps/gittensory-ui/src/routes/docs.maintainer-self-hosting.tsx @@ -203,6 +203,94 @@ function MaintainerSelfHosting() { Tuning your reviews for gate semantics and this section for running the service yourself.
+ +
+ "Hosted" here means the private managed-beta shared gittensory App
+ described in GitHub App configuration — a repo installed
+ there is reviewed by gittensory's own cloud Worker and its own database.
+ "Self-host" means your own container from{" "}
+ Quickstart, with its own GitHub App (or
+ brokered Orb enrollment) and its own data store. There is{" "}
+ no automated migration path between the two today — moving a repo is a
+ manual App swap plus re-creating whatever settings you had, not a toggle.
+
/ready is healthy — see{" "}
+ Quickstart — before touching the hosted
+ install, so the repo is never briefly reviewed by nothing.
+ src/selfhost/setup-wizard.ts always mints a distinct App tied to your
+ instance's own webhook URL.
+
+ Hosted-side settings live in gittensory's own cloud database, keyed by repo full name —{" "}
+ resolveRepositorySettings (src/settings/repository-settings.ts)
+ reads them from env.DB, which is a completely different database instance than
+ your self-host container's. A self-host instance has no access to, and no import path
+ for, whatever thresholds, gate modes, or review-mode settings you configured on the hosted
+ side through the control panel or API. If you want the same behavior, you have to
+ re-configure it on the new instance from scratch — there is no export/import tool for this
+ today.
+
+
+ One thing genuinely does carry over: a repo's own .gittensory.yml
+ {" "}
+ (config-as-code), because it lives in the repository's git history, not in either
+ service's database. resolveRepositorySettings overlays it on top of
+ whatever DB settings exist, on either hosted or self-host — so gate-mode overrides,
+ thresholds, and other settings expressed in that file apply identically the moment the new
+ App starts reviewing, with nothing to re-enter.
+
+ What stays identical for contributors either way: the review still posts as a{" "}
+ gittensory[bot]-style comment (under your own App's slug once you migrate,
+ not literally gittensory[bot]) plus the same check-run shape, and the gate
+ semantics in Tuning your reviews and{" "}
+ How reviews work are unchanged — only the
+ infrastructure and the settings storage location differ.
+
+ The reverse migration has the same shape and the same gap: uninstall your self-host App from
+ the repo, install the shared hosted App (if you have managed-beta access — see{" "}
+ GitHub App configuration), and re-create any DB-backed
+ settings on the hosted side. .gittensory.yml again carries over for free since
+ it travels with the repo; nothing else does. Your self-host instance's data volumes are
+ untouched by this — see{" "}
+ Uninstalling and decommissioning if you also
+ intend to shut the instance down rather than keep it idle or reuse it for other repos.
+
+ Tearing an instance down cleanly touches four independent things: the GitHub App + installation, the data volumes, brokered-mode enrollment, and control-panel access. None of + this is scripted today — do each step deliberately, in this order, and decide what to keep + before you delete anything. +
+ +
+ Uninstalling stops GitHub from sending any further webhook events and immediately revokes
+ the App's installation tokens — nothing on the self-host side needs to be told; there
+ is no installation deleted webhook handler to run first. From the
+ repo or org: Settings → Integrations → GitHub Apps → your App → Uninstall. Do this before
+ stopping the container so you are not left with a dangling install pointed at a dead webhook
+ URL.
+
+ If you only want to pause reviews without losing the App's configuration (permissions, + webhook URL, private key), suspend the installation instead of uninstalling it — GitHub + stops delivering events to a suspended install but keeps everything else intact for a later + resume. +
+ +
+ Stopping the container does not delete anything — docker compose stop or{" "}
+ docker compose down (without -v) leaves every named volume (
+ gittensory-data, gittensory-pg, qdrant-data,{" "}
+ gittensory-backups, grafana-data, and the rest declared in{" "}
+ docker-compose.yml) on disk, along with the ./gittensory-config{" "}
+ host directory (a bind mount, not a named volume, so it is never affected by -v{" "}
+ either way). Pick one:
+
docker compose down -v{" "}
+ permanently destroys review history, settings, and the vector index with no recovery path —
+ the volumes are the only copy. See{" "}
+ Backup and scaling before running it on
+ an instance you care about.
+
+ If this instance runs in brokered mode (ORB_ENROLLMENT_SECRET is set — see{" "}
+ GitHub App and Orb), be aware there is{" "}
+ no self-service revocation endpoint today — the "Minimum broker
+ safeguards" checklist on that page lists a revocation path as a prerequisite for a
+ public brokered rollout that has not shipped yet. An enrollment record (
+ orb_enrollments) lives in gittensory's own central database, not your
+ container, and nothing in this codebase writes a revoked_at value to it outside
+ of tests. Practical steps until that exists:
+
ORB_ENROLLMENT_SECRET go with it — with nothing
+ polling or listening, the secret is inert even if it still resolves to a valid enrollment.
+
+ ADMIN_GITHUB_LOGINS is read fresh from the environment on every control-panel
+ request (isAuthorizedGitHubSessionLogin in src/auth/security.ts) —
+ it is never cached at startup or baked into an issued session. To remove someone's
+ operator access, delete their login from the comma/whitespace-separated list in{" "}
+ .env and restart the gittensory service so the process picks up
+ the new value:
+
+ This takes effect on their very next control-panel request after the restart — no signed-in + session is grandfathered in, because authorization is re-checked against the current + allowlist every time, not read from the session itself. If you are decommissioning the whole + instance rather than removing one operator, this step is moot once the container is stopped. +
); }