On this page
ADR-0047: Onboarding a project is connecting its repository, and one rule engine checks it
Status: Accepted (WP-80). Specified in plan 13 §11; implemented in crates/commonlayer-github/src/service/onboarding.rs, src/service/scans.rs and src/domain/rules/.
Context
A project used to be proposed by filling in a form with a repository URL. Nothing showed that the person controlled the repository, and whether it followed the image and chart standards came out later, in review or at the first release. The guardrail checks of a connected repository were a second, separate list of conditions.
Decision
- A project is onboarded by connecting its repository through the GitHub App: install
the App, pick a repository, read the scan, fix what it reports, propose.
POST /projectsis refused (projects.onboarding_required) while managed repositories are required. - The installation is bound to a person only after GitHub confirms it. The callback
exchanges the OAuth code and the installation must be in the list GitHub returns for
that person; the
installation_idin the query string is only a hint. The state is single-use, bound to the person and valid for 15 minutes. No user token is stored. - The callback decides once. A GitHub account that is linked to another CommonLayer
account, or a person who already linked a different GitHub account, binds nothing
(
auth.identity_taken,auth.github_identity_mismatch); the refusal is audited. Access, onboarding and the successor rule all act on the one linked account. - Only an administrator of the repository, as GitHub reports it, can onboard it.
- The onboarding scan is static: it reads the tree and files through the API and executes nothing from the repository. It checks connection, structure, manifest, image, chart, CI, template and repository settings.
- The scan and the continuous guardrail check are the same engine and the same rule
catalogue (
GET /repository-rules). A rule is a pure function with an id, a reference to the standard it enforces, and results that name the file and line. - The catalogue is tested against this repository: the project template and every first-party project must pass, and the template states the ruleset version it satisfies. A rule that the template fails is a bug in the rule or in the template.
- Required rules block approval. A platform reviewer can waive one for a project in review, as a person in a session, with a written reason; waivers are public.
- An unknown rule id in the
github.guardrails_requiredsetting makes the scan outcomeerror. It is not ignored. - While managed repositories are required, approval needs a finished scan of the
primary repository: no scan, a running scan or an
erroroutcome refuse it (projects.repository_not_scanned). - In development and test a development provider stands in for GitHub
(
github.provider = "development", refused by configuration validation anywhere else), with a portal page in place of GitHub's installation page, as the simulated payment provider does for payments. What it produces is labelled development data.
Alternatives rejected
- Running the project's build during onboarding. It would execute third-party code on the platform before anyone has reviewed it. The first release submission builds and verifies in the pipeline that exists for that.
- A separate checklist for onboarding. Two lists drift; a project could pass onboarding and fail the guardrails the next day for the same file.
- Trusting the installation id from the callback. Anyone can type a number.
Consequences
- A repository that is not on GitHub cannot be onboarded while managed repositories are required. Turning the setting off restores the form-based proposal, without the stewardship guarantees.
- The rules know one template version. A second version needs versioned rule sets.
- First-party projects in this repository are built by its own workflows, so their CI rules are reported as not applicable; the template carries the workflows external projects use and is checked in full.