DOCS/GOVERNANCE — BRANCH PROTECTION, 2 APPROVALS, SIGNED TAGS
sdk-v2/docs/GOVERNANCE.md · commit 96368332 · GLI CSR §2.2: GLI-19 App. B repository controls · ← package index · raw on GitHub ↗GOVERNANCE — repository controls for the RAIN RNG (GLI-19 App. B; GLI CSR §2.2 "Software Verification"; UKGC RTS 8.25/8.29)
This document says how the repository is protected, who may approve what, and how a lab can verify it from GitHub itself. It closes the review finding "CI in repo, two maintainers per PR" (lab/REVIEW-RESPONSE-R1.md item 4). Companion documents: lab/process/CHANGE-CONTROL.md (procedure per change), lab/process/SDLC.md (environments, tests), lab/process/SECURITY-PROGRAM.md (pen-test / audit / disclosure cadence).
1. Roles
| role | who | what |
|---|---|---|
| Maintainer team A | @Quecko-Org/rain-maintainers-a (placeholder handle — see §5) |
code owner of every path; may approve PRs; may cut and sign release tags |
| Maintainer team B | @Quecko-Org/rain-maintainers-b (placeholder handle — see §5) |
same; the second, independent approver |
| Release manager | one member of A or B, named per release in CHANGELOG.md |
runs PUBLISHING.md, signs the tag, submits lab/FINGERPRINTS.json |
| Lab / regulator | read access | verifies: CI status on the tagged commit, two approvals, signed tag, fingerprints |
Segregation of duties: the PR author can never be one of the two approvers. CODEOWNERS requires both teams on every path; branch protection turns that into an enforced gate.
2. Branch protection (to apply on main; identical on release branches release/*)
GitHub → Settings → Branches → Add rule for main (or a repository ruleset — same settings):
- Require a pull request before merging — no direct pushes, no admin bypass ("Do not allow bypassing the above settings")
- Required approvals: 2
- Dismiss stale approvals when new commits are pushed
- Require review from Code Owners (→
.github/CODEOWNERS: both maintainer teams on every path) - Require approval of the most recent reviewable push (an author's own last push cannot self-approve)
- Require status checks to pass before merging, "Require branches to be up to date": required checks =
ci / build · typecheck · unit (KATs, crash, selftest, e2e) · python mirror,ci / reproducible build · fingerprint drift (lab/FINGERPRINTS.json),ci / dependency review (supply chain, PRs only),ci / npm audit (production deps) - Require signed commits
- Require linear history
- Require conversation resolution before merging
- Lock force pushes / deletions (both off for everyone including admins)
- Tag protection ruleset:
sdk-v*tags may only be created by the two maintainer teams and must be signed (git tag -s).
Equivalent gh command (run once by an org owner; adjust the repo):
gh api -X PUT repos/Quecko-Org/<repo>/branches/main/protection --input - <<'JSON'
{ "required_status_checks": { "strict": true, "contexts": [
"ci / build · typecheck · unit (KATs, crash, selftest, e2e) · python mirror",
"ci / reproducible build · fingerprint drift (lab/FINGERPRINTS.json)",
"ci / dependency review (supply chain, PRs only)", "ci / npm audit (production deps)" ] },
"enforce_admins": true,
"required_pull_request_reviews": { "required_approving_review_count": 2, "dismiss_stale_reviews": true,
"require_code_owner_reviews": true, "require_last_push_approval": true },
"restrictions": null, "required_linear_history": true, "allow_force_pushes": false, "allow_deletions": false,
"required_conversation_resolution": true, "required_signatures": true }
JSON
3. What CI enforces on every PR (.github/workflows/ci.yml)
| job | command | what it proves |
|---|---|---|
| build-test | npm ci && npm run build && npm run typecheck && npm run test --workspaces; npm run test:py |
KATs (FIPS 180-4, RFC 4231, NIST CAVP HMAC_DRBG ×32, RFC 8439, keccak), ceremony tests, persist-before-reveal under injected crashes, self-test error state, e2e node; Python mirror byte-identical |
| fingerprint-drift | npm run lab:verify-build ×2; git diff --exit-code lab/FINGERPRINTS.json |
the clean rebuild is byte-identical to the frozen manifest → any RNG-affecting change must refreeze the manifest in the same PR (which makes the change visible to the lab, CHANGE-CONTROL §3.5) |
| dependency-review | actions/dependency-review-action |
no new dependency with a high/critical advisory enters via a PR |
| audit | npm audit --omit=dev --audit-level=high |
production dependency tree (ws; optional pg, ethers) is clean |
4. Release and tag policy
- PR "release sdk-vX.Y.Z" (version bump, CHANGELOG, refreezed
lab/FINGERPRINTS.json) — 2 approvals, CI green. - Release manager:
git tag -s sdk-vX.Y.Z -m "..."on the merge commit;git push origin sdk-vX.Y.Z. npm publish --provenancefrom a GitHub Actions release workflow (Sigstore attestation links the npm tarball to this repo + commit) — seePUBLISHING.md§3. Not yet executed: the owner decides the publication scope.- The lab receives: tag name, commit SHA,
lab/FINGERPRINTS.json, CI run URL, tarballintegrityhashes.
A lab can verify independently: git verify-tag sdk-vX.Y.Z (signature), gh run list --commit <sha> (CI), gh pr view <n> --json reviews (two approvals by code owners), npm run lab:verify-build (manifest).
5. Status — honest
| control | state |
|---|---|
| CI workflow in repository | present (.github/workflows/ci.yml, this commit) — runs on the first push to a GitHub repo with Actions enabled; not yet exercised on GitHub: the mirror branch sdk-v2 on Quecko-Org/rain-playmarket-fe-dev is a force-pushed snapshot pushed with a PAT that lacks the workflow scope, so GitHub rejects .github/workflows/* from it — the mirror carries the file as .github/workflows-pending/ci.yml; an org owner moves it back (git mv) or pushes with a token that has the scope (scripts/publish-branch.sh) |
| CODEOWNERS, PR template | present; the team handles @Quecko-Org/rain-maintainers-a/-b are placeholders until the org owner creates the two teams (or substitutes two named users) |
| Branch protection (2 approvals, required checks, signed tags) | documented above; NOT yet applied — requires org-owner rights on GitHub. Until then the repository is effectively single-maintainer, as SDLC.md §5 states |
| Second maintainer | pending — the project has one active maintainer today; the second approver must be a real second person for the control to mean anything. The lab should treat "two approvals" as to be evidenced from PR history after enablement, not as met |
| Signed commits/tags | keys not yet enrolled; policy stated |
← Back to the package index · Rendered 2026-09-14 09:34 UTC from the repository copy; the markdown in the zip / repo is the document of record.