SurfSense/CONTRIBUTING.md
Anish Sarkar a989bb55d0 ci: keep only repo-wide checks shared and have each product lint, scan and test itself
code-quality.yml ran every pre-commit hook minus a skip list in each job, so
newer hooks leaked in: check-docs ran four times per PR, the translation hooks
ran in every job, and Biome ran on every PR whether the web app changed or not.
The desktop backend had no security scan at all, the gates counted a cancelled
or timed-out job as passing, and hooks pinned tool versions a second time.

- code-quality.yml keeps only what belongs to no product, run by hook name on
  every PR: file checks, check-docs and detect-secrets
- docker-tests.yml replaces backend-tests.yml and e2e-tests.yml for
  surfsense_backend and surfsense_web: ruff, bandit, Biome, backend unit and
  integration tests, and the e2e journey, each job run only when its files
  change
- desktop-tests.yml filters per job instead of per workflow, adds bandit for
  the desktop backend, and checks translations, failing on a stale en.json
  that typecheck used to regenerate silently
- each workflow ends in a gate (Docker Gate, Desktop Gate, Quality Gate) that
  always reports and fails on failed or cancelled jobs, so it can be made a
  required check without blocking PRs that don't touch that product
- bandit is split into bandit-docker and bandit-desktop aliases, so each
  product scans only its own code
- the Biome hook runs only when a commit touches surfsense_web, instead of
  blocking every commit on the app's existing formatting errors
- Biome and formatjs run from each app's own install (pnpm exec, and a new
  translations:verify script), so their versions live only in package.json
- hook versions updated: pre-commit-hooks v6.0.0, bandit 1.9.4, commitizen
  v4.19.0, and ruff v0.15.8 to match surfsense_backend's own ruff
- surfsense_web's pnpm comes from its own package.json and the root
  package.json is removed; every action is on its latest version
- CONTRIBUTING.md, docs/contracts/README.md, auth_mint.py, the translate
  skill and localization.md name the new workflows and commands
2026-09-25 18:23:56 +05:30

4.9 KiB

Contributing

Bug fixes and docs are welcome without asking first. A new feature starts with a short design proposal, so we can agree it belongs here before you spend time on a large PR. If you are not sure an idea fits, ask on Discord or in Discussions first.

Security: SECURITY.md. Conduct: CODE_OF_CONDUCT.md.

Find something to work on

Read before you change anything

docs/README.md explains how the docs are organised. For the desktop app, start with docs/architecture/overview.md, the map of surfsense_local/, then read the doc for the feature you are touching. Each feature doc links the decision records in docs/adr/ that explain why it is built the way it is.

Getting set up

This repo holds four products. Clone it once, then open the README for the product you want to change. You do not need to run the other three.

If you want to work on Open
Desktop app surfsense_local/README.md
MCP server surfsense_mcp/README.md
API / scrapers surfsense_backend/README.md
Self-host web UI surfsense_web/README.md

The web UI needs the API running. Desktop does not. MCP talks to any backend over HTTP.

git clone https://github.com/<you>/SurfSense.git
cd SurfSense
git checkout dev
git checkout -b fix/short-name

We merge through dev. Open your PR against that branch.

How a change gets in

  • Bug fix or small change. Open a PR against dev. If there is an issue, Fixes #123 links it and closes it on merge.
  • New feature. First open a PR that adds a proposal, docs/proposals/<name>.md, marked status: proposed. The header it needs is in docs/README.md. Once a maintainer accepts it, the code follows in its own PRs. The last of them moves the design into docs/architecture/, records any lasting decision in docs/adr/, and deletes the proposal.
  • A change to a contract. Files in docs/contracts/ are the interfaces between two parts of the repo, such as the license file the backend issues and the desktop app reads. Changing one needs the agreement of the owners of both sides.
  • Reversing a recorded decision. An accepted ADR is not rewritten. The change comes with a new ADR that supersedes it (docs/adr/README.md).

Pull requests

Small, focused PRs are easier to review.

  • Say what changed, why, and how you tried it.
  • If your change alters behaviour that a doc in docs/architecture/ describes, update the doc in the same PR. If it fixes a Known gap, delete that line.
  • Run the tests for what you changed. The commands are in each product's README and in the Testing table in AGENTS.md.
  • After editing anything under docs/ or plans/, run python scripts/check_docs.py.
  • Allow edits from maintainers lets us help on the branch.
  • New files follow AGENTS.md. Existing packages do not need a layout rewrite unless that is the issue.
  • surfsense_backend/app/proprietary/ is Business Source License 1.1. Ask a maintainer before changing it.
  • Keep .env and secrets out of the commit.

Review and merge

CI on the PR should be green. code-quality.yml runs the docs checker, file checks and a secrets scan on every PR. Each product lints, scans and tests itself when its files change: docker-tests.yml for surfsense_backend and surfsense_web, including the end-to-end journey, and desktop-tests.yml for surfsense_local. CODEOWNERS asks the maintainer who owns the files you touched to review. One maintainer approval is enough to merge. Merged work lands on dev and reaches main with the next release.

If you work with a coding agent, AGENTS.md gives it the same rules, along with the repo's layout and commands.