Gatekeeper
Gatekeeper is the CI check that measures a pull request’s log coverage and either lets it through or opens an auto-fix pull request with the missing logs. The GitHub Action calls one backend route.
Code: backend controller/GatekeeperController.java, controller/GatekeeperKeyController.java,
service/gatekeeper/{GatekeeperAuth,GatekeeperTarget,GatekeeperThreshold,GatekeeperCiKeys}.java.
POST /api/v1/gatekeeper/check
Section titled “POST /api/v1/gatekeeper/check”{ "branch": "feature/login", "baseCommit": "4f2a9c1", "commit": "9b81e0d", "repoUrl": "https://github.com/acme/payments", "changedFiles": ["src/main/java/acme/Login.java"], "logCoverageThreshold": ""}| Field | Required | Rule |
|---|---|---|
branch | yes | A git branch name (git check-ref-format --branch), at most 255 characters |
commit | yes | A commit sha, 7–40 hex characters |
baseCommit | no | A commit sha, 7–40 hex characters |
repoUrl | yes | The repository’s https URL naming owner and repository; at most 2048 characters |
changedFiles | yes | A list of 1 to 10 000 non-blank paths of at most 4096 characters; an empty list is a 400 “changedFiles must list at least one path” (backend 05c9a46c, 2026-10-21) |
logCoverageThreshold | no | A number; "" (an unset Actions variable) means “not supplied” |
githubToken | no | Used for the auto-fix pull request only when the scan’s owner has no GitHub token |
The answer (GatekeeperResponse) is always 200 once a measurement exists:
{ "status": "block", "message": "Not good", "prLink": "https://github.com/acme/payments/pull/42", "coveragePercent": "61.40", "threshold": "80", "thresholdSource": "server"}statusisallowwhencoveragePercent ≥ threshold, otherwiseblock. Onblockthe scan is saved and the log generator opens a pull request whose URL isprLink.coveragePercent,thresholdandthresholdSourceare strings, reported on both outcomes, so the pipeline prints exactly what the server compared.- A scan that produced no coverage measurement is a 500 (
the scan produced no coverage measurement for commit …), never a 0 % block. - A
branchthat does not exist in the repository is a 422 “Branch ‘<branch>’ does not exist in <repoUrl>.” (GatekeeperCheckout, backend05c9a46c, 2026-10-21, dev and prod). It used to be a 500 from the failed clone. - Both outcomes are posted to the workspace’s Discord channel when one is connected.
Credentials
Section titled “Credentials”Two credentials are accepted, both as Authorization: Bearer …:
| Credential | Who uses it | Workspace |
|---|---|---|
Gatekeeper CI key (lgck_live_…) | The GitHub Action (secret LOGRITE_API_KEY) | The key’s own workspace |
| Login JWT | The dashboard | Every workspace the user belongs to; the newest matching scan wins |
An unknown or revoked CI key is 401 invalid or revoked Gatekeeper CI key; no credential is
401.
CI keys are managed by a signed-in Maintainer or above at /api/v1/gatekeeper/keys
(POST ?workspaceId=&name= mints and returns the plaintext once, GET ?workspaceId= lists,
DELETE /{id}?workspaceId= revokes). An lgp_live_ API key or an MCP connection is refused: no
credential can mint a credential. Revoking a key in another workspace answers 404.
Which repository and workspace
Section titled “Which repository and workspace”The check inherits its project and scan profile from the latest prior scan of the same
repository inside the caller’s workspace (GatekeeperAuth):
repoUrlis normalised: trimmed, trailing/removed, one trailing.gitremoved.- The prior scan is the newest
log_scan_resultwhose branch link starts with that URL plus/(stored links are<repo>/tree/<branch>, Bitbucket/branch/), compared case-insensitively. - A repository the caller’s workspace never scanned answers 404
No prior scan found for repository '…'. Run an initial scan on this repository before calling the gatekeeper.— even when another workspace scanned it, so the route cannot enumerate other tenants’ repositories.
The threshold
Section titled “The threshold”GatekeeperThreshold.resolve picks, in order:
| Source | thresholdSource |
|---|---|
logCoverageThreshold in the request, when it is a number | request |
The workspace setting gatekeeper.coverageThreshold | workspace |
The backend default GATEKEEPER_DEFAULT_COVERAGE_THRESHOLD (gatekeeper.default-coverage-threshold, default 80) | server |
A configured default that is not a percentage 0–100 is replaced by 80 at startup, with a log
line. A request value above 100 is honoured as sent.
Public-route listing
Section titled “Public-route listing”/api/v1/gatekeeper/check is in ApiChainPolicy.PUBLIC_API_PATHS and in
ApiPublicMachineSurface (NON_BEARER_CREDENTIAL): the Spring API chain
(SECURITY_API_CHAIN_ENABLED) cannot recognise an lgck_live_ key, so the route is let through
the chain and GatekeeperAuth verifies the CI key or the JWT itself and answers 401 to anything
else.