Project
Maintaining CV-Scope
How the repository is protected against bad or malicious changes, the GitHub
settings that go with the files in .github/, and how to review a pull
request safely.
How a change reaches main
- A contributor forks the repository and opens a pull request. Nobody without write access can push to this repository.
- For outside contributors, GitHub waits for a maintainer to press Approve and run before any workflow runs their code.
- CI runs with a read-only token and no secrets:
repo-guardrejects keys, licences, databases, model weights, pickles, binaries, archives, pictures or videos outsidedocs/, files over 3 MB, invisible Unicode characters, dependencies from anywhere but PyPI and the npm registry, andpull_request_target/workflow_runworkflows (.github/scripts/repo_guard.py);backend: ruff and the full pytest suite;frontend:npm ci --ignore-scripts(no install scripts run), type check, tests, production build;dependency-review: fails if the change adds a dependency with a known high-severity vulnerability.
- The branch ruleset requires all four checks, an approving review from a
code owner (
.github/CODEOWNERS) given after the last push, resolved review threads and an up-to-date branch. It allows squash merges only and blocks force pushes and deletion ofmain. - Dependabot proposes dependency updates weekly, waiting 7 days after each
release (
.github/dependabot.yml).
The checks run the pull request’s own version of the workflows and the guard
script. A pull request that edits .github/ can change what “passed” means,
which is why every file there has a code owner and must be read line by line.
One-time settings after the first push
-
Branch ruleset. Either with the GitHub CLI:
bash gh api --method POST repos/ajm2004/CV-Scope/rulesets --input .github/rulesets/protect-main.jsonor in the browser: Settings → Rules → Rulesets → New ruleset → Import a ruleset, and choose
.github/rulesets/protect-main.json. The repository administrator is on the bypass list (Always): you can push straight tomainand merge your own pull requests without a second reviewer, while everyone else must go through a pull request with passing checks and your approval. CI still runs on every push tomain; check the Actions tab after pushing. The bypass covers every rule, including force pushes, so never usegit push --forceonmain. For a stricter setup, set the bypass to For pull requests only: then your own changes also go through a pull request, which you can merge without a second reviewer. -
Settings → General → Pull Requests: allow squash merging only; turn on Always suggest updating pull request branches and Automatically delete head branches.
-
Settings → Actions → General:
- Actions permissions: Allow ajm2004, and select non-ajm2004, actions and
reusable workflows, with Allow actions created by GitHub ticked
(the workflows use only
actions/*). If the page offers Require actions to be pinned to a full-length commit SHA, tick it. - Approval for running fork pull request workflows from contributors: Require approval for all external contributors.
- Workflow permissions: Read repository contents and packages permissions; untick Allow GitHub Actions to create and approve pull requests.
- Actions permissions: Allow ajm2004, and select non-ajm2004, actions and
reusable workflows, with Allow actions created by GitHub ticked
(the workflows use only
-
Settings → Advanced Security (or Code security): turn on the dependency graph, Dependabot alerts, Dependabot security updates, secret scanning with push protection, CodeQL Default setup, and Private vulnerability reporting (
SECURITY.mdpoints reporters there). -
Your account: two-factor authentication with a passkey or security key. Give helpers the Triage role; anyone with Write can approve and merge. Add a second code owner to
.github/CODEOWNERSonly when you trust them with the whole repository.
Reviewing a pull request safely
- Read before you run.
scripts/setup.*,npm install,pip install -eand the test suite all execute code from the pull request. Read the diff first. If you need to run it, use a throwaway virtual machine or a GitHub Codespace, not the computer with your cameras, recordings and keys. - Press “Approve and run” only after a first look at a new contributor’s
pull request, especially at
.github/andscripts/. - Read these paths first and completely:
.github/,scripts/, Dockerfiles,backend/pyproject.toml,frontend/package.jsonandpackage-lock.json,backend/pathscope/models/catalog.pyandbackend/pathscope/recognition/catalog.py. The catalogs hold the download URLs of model weights, and downloads are not checksum-verified: a changed URL can deliver a.ptfile, which is a Python pickle that runs code when it is loaded. - Red flags: new URLs or hosts; long base64 or hex strings; minified,
generated or oddly formatted code;
eval,exec,subprocess,pickle,torch.load,os.system; tests changed so they assert less; a lockfile change without a matchingpackage.jsonchange (ask the contributor to drop it and regenerate it yourself); a “typo fix” that also touches CI; a large reformatting that hides a small change. - Merge what you reviewed. If commits arrive after your review, the ruleset dismisses your approval; use Files changed → Changes since your last review before approving again.
- Dependabot pull requests get the same care: read the release notes of major updates, and do not merge a dependency you cannot explain.
Releasing the Windows installer
The installer (installer/, described in installer/README.md) is built
and published by .github/workflows/installer.yml when a v* tag is pushed:
- Before a release, run
python installer/update_pins.py(uv on PATH) and review the diff ofinstaller/pins.jsonandinstaller/constraints.txt: they fix what every installation downloads, including the SHA-256 of the PyTorch wheels, uv and Inno Setup. A changed URL or hash deserves the same care as a new dependency. - Set the version in
backend/pyproject.tomlandbackend/pathscope/__init__.py, and merge. git tag vX.Y.Zon that commit andgit push origin vX.Y.Z. The workflow checks that the tag matches the version, builds the installer on a clean Windows runner, installs, starts, benchmarks and uninstalls it (installer/smoke_test.ps1), then creates the release withCV-Scope-Setup-Windows-x64.exeandSHA256SUMS.txt. Only that last job hascontents: write, which it requests itself; the repository default stays read-only.- The website and the README link to
releases/latest/download/CV-Scope-Setup-Windows-x64.exeand.../SHA256SUMS.txt: never rename these assets, and publish releases (not drafts) so that latest points at them.
installer/ is owned by the code owners like scripts/: the installer
runs on users’ machines and decides what they download.
If something bad was merged
Revert it with a pull request (git revert <commit>), check the Actions logs
of the runs that included it, and if a release or users were affected,
publish a security advisory from the Security tab. The repository holds no
secrets, so there is nothing to rotate unless one was committed by mistake;
in that case revoke it first, then clean the history.
This page is docs/maintainers.md from ajm2004/CV-Scope@eaf904a
, committed 30 September 2026. The repository is the source of truth; this site renders
it.