SurfSense/docs/contracts
Anish Sarkar 8850a6ca57 ci(legacy-split): remove the self-hosted image workflows from dev
docker-build.yml on main published `latest` and `0.0.40` for the
self-hosted images, and every desktop release merge started it, so the
next one would have replaced the 0.0.41 images released from `legacy`.
The self-hosted stack now builds, tests and releases from the `legacy`
branch only.

- Delete docker-build.yml and docker-tests.yml.
- Drop the release-runbook paragraph about the image build on main.
- Point the docs' links to docker-build.yml at the legacy branch, and
  update the comments and CONTRIBUTING lines that named either workflow.
2026-10-24 18:02:18 +05:30
..
export-sample docs: reorganize engineering docs under docs/ 2026-09-22 21:27:26 -07:00
license-sample docs: reorganize engineering docs under docs/ 2026-09-22 21:27:26 -07:00
01-license-file.md feat(backend): serve the license portal from backend/license/ 2026-10-23 17:49:08 +02:00
02-scraper-api-auth.md refactor(backend): move plugins/ into backend/, run by server/ 2026-10-23 17:49:08 +02:00
03-export-bundle.md docs(import): align thread recovery documentation 2026-10-16 01:24:52 +08:00
04-sunset-flag.md docs: reorganize engineering docs under docs/ 2026-09-22 21:27:26 -07:00
05-desktop-telemetry.md feat(desktop): leave updates to the package manager that installed the app 2026-10-23 22:39:25 -07:00
check-export-sample.py docs: reorganize engineering docs under docs/ 2026-09-22 21:27:26 -07:00
README.md ci(legacy-split): remove the self-hosted image workflows from dev 2026-10-24 18:02:18 +05:30

Contracts

A contract is a frozen file describing something that crosses from one tree to another. Each side builds and tests against the file and its fixture, not against the other side's code. The first four were frozen for the 2.0 launch.

# Contract Producer Consumer In use since
1 License file surfsense_backend license routes surfsense_local license module 2.0.0
2 Scraper API auth the plugin host; surfsense_backend capabilities routes the desktop app; surfsense_mcp plugin host and app since 2.2.1; backend and MCP not built
3 Export bundle surfsense_backend export surfsense_local import 2.0.0
4 Sunset flag surfsense_backend /health legacy desktop v0.0.40, whose source is at tag archive/hosted-2026-09 v0.0.40, 12 Sep 2026; the flag reads true from T-0, 18 Sep 2026
5 Desktop telemetry Electron main (the update check and the usage report); surfsense_local backend (the local summary) surfsense_web's /api/updates and /api/usage routes; the app's UI (the bridge) not released

Fixtures

  • export-sample/ is an unzipped contract-3 bundle. Tests zip it in a setup step. Check it with python3 check-export-sample.py.
  • license-sample/ holds contract-1 files signed by a test key, plus the generator that makes them. Regenerate and self-check with node license-sample/generate.mjs.

Both checks are dependency-free and run from this folder.

Five tests read files in this folder by path. surfsense_local/backend/tests/integration/migration/test_import.py, surfsense_local/backend/tests/integration/license/test_license.py and surfsense_backend/tests/unit/services/test_account_export.py read the fixtures; surfsense_backend/tests/integration/test_account_export.py runs check-export-sample.py against a real export; and the release build's test-key guard, surfsense_local/backend/tests/packaging/test_license_key.py, reads the test public key. Moving this folder means updating all five in the same change, plus the skip entry in scripts/check_docs.py and the docs/contracts/** path filter in .github/workflows/desktop-tests.yml.

Changing a contract

A contract changes by a pull request that the owners of both sides approve. CODEOWNERS requests their review, but GitHub accepts one approval, so the second is by agreement. If the change is not backward compatible, bump the version field the contract names (format for the bundle, the alg/field list for the license file) and update the fixture in the same PR. Never change a fixture without changing the contract text that describes it.