This site is being rebuilt and some pages are out of date. For current details, write to reach@inorbit.hr. This notice goes away when the rebuild is done.

No analytics unless you allow it, no tracking. This site keeps in your browser the language you pick, the theme, its colour, which site you chose, the currency on the pricing page and that you closed this notice; signing in adds session cookies. The legal page has the details.

Sign in

← Back to Platform

RFC 0036open2026-10-03

Lab repository sync, the team's Git as the source of truth

A lab bound to a GitHub repository reads its documents from it, records every merge as a version, and turns an edit in the console into a pull request.

Problem

The Lab (RFC 0035) keeps a team's RFCs, studies and diagrams in the platform first: a labs service stores every version, the console edits them, and an export gives the files back. That suits a team starting from nothing. It does not suit the teams RFC 0035 was written for, whose decisions already live in Git next to the code, reviewed in pull requests like the code. For them a second copy in the platform is a copy that drifts, and an editor that writes around their review process is one they will not use.

RFC 0035 decided the direction: the repository stays the source of truth, and an edit in the console becomes a pull request. It left the mechanism open. The platform now has the pieces it needs: connections (RFC 0018) hold outside credentials and run actions under grants, the agent (RFC 0029) reaches systems inside a company's network, and the labs service records versions with their author and message.

Proposal

A GitHub connection kind

A new connection kind, github, authenticated as a GitHub App that the platform registers once and a team installs on the repositories it chooses. GitHub issues an installation access token that "will expire after 1 hour" and can be limited to named repositories and permissions when it is made (GitHub docs). The connections service mints one per action, for the one repository and the permissions that action needs, and never keeps it.

The App asks for the least that the sync needs (permissions):

Permission Level For
Metadata read required by GitHub for every App
Contents read reading trees and files
Contents write a branch and a commit for a proposed change
Pull requests write opening the pull request

The kind's actions, each with its class (RFC 0018):

Action Class Does
read_tree read lists the files under the lab's paths at a ref
read_file read one file's text at a ref, with its blob id
propose write_reversible a branch from the lab's branch, one commit with the changed files, a pull request; closing the pull request undoes it
status read the installation, the repository and the last delivery

Push and pull request events arrive through the App's webhook, verified with its signing secret like any incoming hook (webhook-in), and are routed to the lab bound to that repository. A team that runs GitHub Enterprise or GitLab inside its network uses the agent as the executor later; the actions stay the same.

A lab bound to a repository

A lab's settings gain a source: the connection, the repository, the branch it follows (the default branch unless named) and the paths it reads, by default the layout iohr lab check already reads (docs/rfcs/, docs/studies/, the lab's redaction.json) plus docs/lab/diagrams/ for diagrams as JSON.

  • Binding reads the tree and imports every document and diagram as version 1, with the commit it came from. The redaction config in the repository replaces the one in the platform; from then on it is edited in the repository.
  • A push to the followed branch records a new version of each changed file: the commit's id, its subject as the version's message and its author. An author is shown as the account member whose verified e-mail matches, and otherwise by name as Git recorded it. A file deleted in the repository is archived in the lab, never erased.
  • An edit in the console on a bound lab is a proposal, not a version: saving opens (or updates) a pull request with that one document on a branch named after it. The document shows the open proposal and its review state on GitHub. The version is recorded when the merge arrives as a push, so the lab and the branch never disagree.
  • A conflict (the file changed on the branch since the proposal's base) is shown in the console with the diff; the person rebases the proposal on the newest version or keeps it as it is for GitHub to resolve.
  • Comments and reviews in the console stay in the platform and are linked from the pull request's description; the pull request's own review stays on GitHub. A lab can require both.

A diagram is drawn here in the RFCs product; this page does not show diagrams yet.

Safe by construction

  • The App reaches only the repositories a team installs it on, and each token only the one repository and permissions of the action that asked for it.
  • Every read, proposal and received event is in the audit log as who, what and outcome, with repository and commit ids, never file contents.
  • Document text is customer data: it is never logged, never put in an error or a URL, and no model reads it in this phase.
  • Unbinding stops the sync and keeps the lab's history; uninstalling the App on GitHub does the same from the other side, within one delivery.
  • Actions cost units (compute per action) and are rate limited per installation, below GitHub's own limits.

Alternatives considered

A personal access token. The quickest to build and the wrong default: it acts as a person, usually across every repository that person can reach, and lives until someone revokes it. An App installation is scoped to the repositories chosen and its tokens last an hour.

Deploy keys. Scoped to one repository, but they speak Git over SSH and cannot open a pull request, so every proposal would need a second credential.

Polling the repository. No webhook to verify, and minutes of lag and wasted calls on every quiet repository. Events with a periodic reconcile (a daily read_tree to catch a missed delivery) give both freshness and correctness.

The platform as the source of truth, with export. What the Lab does today. It stays the answer for teams without a repository; for teams with one it is the drift this RFC removes.

Decision

Open. Proposed: a github connection kind as a GitHub App with the four permissions above and short-lived per-action tokens; a lab bound to one repository, branch and set of paths; merges recorded as versions; console edits as pull requests; the platform's own comments and reviews kept and linked. Order: the kind and binding with import, then push events, then proposals, then GitLab and the agent executor.

Publication

The console's lab settings gain Source (connect GitHub, choose the repository, branch and paths); a bound lab's documents show their commit and any open proposal. The developer docs gain the App's permissions, what the sync reads and writes, and how to unbind.

Status log

  • 2026-10-03: opened, after the connections service landed, as the mechanism RFC 0035 left open for keeping a lab in the team's own repository.
  • 2026-10-04: the github kind is built once, as the GitHub App connector of RFC 0044 (its phase 3), and Lab uses it as the product consumer product:lab through a person's grant: read_tree, read_file, propose and status, with push and pull_request events, installation tokens minted per call and never stored.
  • 2026-10-07: Checked: a github connector exists in the connections catalogue, but no PR builds the sync (#162, #187 and #235 are text and diagrams), and no lab reads a repository. Open.

← Back to Platform