The privacy-safe product, release, reliability, and Foundry evidence contracts for CodeVetter.
Automation readiness contract
This page is the canonical inventory + contract matrix for CodeVetter’s automation readiness. It is the durable answer to “what evidence proves CodeVetter is releasable and diagnosable without centralizing reviewed code, repositories, prompts, or user API keys.”
It is the single home for:
- The surface inventory (landing, desktop, Rust, SQLite, MCP, benchmark, release/updater, docs, weekly canary).
- The privacy-safe product funnel contract (acquisition, download intent, activation, return) and the explicit not-applicable decisions.
- The release, reliability, and Foundry evidence contracts.
- The current baseline evidence (revisions, live landing, updater manifest, canary freshness).
Do not duplicate this matrix elsewhere — link here.
Surface inventory
| Surface | Location | Evidence source | Owner |
|---|---|---|---|
| Landing (Astro) | apps/landing-page-astro/ → Cloudflare Pages codevetter |
deploy-landing.yml + Cloudflare deploy logs + live smoke |
Sarthak |
| Landing agent indexing | llms.txt, /api/ai, robots.txt, sitemap, JSON-LD |
Static export; deploy-landing.yml verifies required routes |
Sarthak |
| Native macOS app | apps/macos/ (SwiftUI + AppKit) |
hosted native qualification, XCUITest, package and release gates | Sarthak |
| Rust product core | crates/codevetter-core/ |
ci.yml core, CLI, MCP, receipt, and collector tests |
Sarthak |
| Local SQLite | rusqlite in Rust backend (no server) |
Local only; observability.rs aggregates locally |
Sarthak |
| MCP sidecar | crates/codevetter-core/src/bin/codevetter-mcp.rs |
ci.yml MCP protocol + stdio lifecycle tests; mcp/sanitize.rs redaction |
Sarthak |
| Benchmark | benchmarks/public-catch-rate/ + scripts/run-catch-rate-benchmark.mjs |
pnpm test:benchmark; public cases committed |
Sarthak |
| Release pipeline | auto-release.yml → release.yml → native-production-qualification.yml → GitHub Releases |
Signed DMG + ZIP + appcast.xml bound by release-readiness.json |
Sarthak |
| Auto-updater | Sparkle 2.9.6 consuming the latest-release appcast.xml |
scripts/verify-release-manifest.mjs validates the live appcast and archive linkage |
Sarthak |
| Docs | docs/ + docs-site/ (Blume) |
docs.yml link + structure validation |
Sarthak |
| Weekly canary | weekly.yml (Mon 09:00 UTC) |
Job summary + canary-evidence.json artifact |
Sarthak |
| Foundry receipts | scripts/emit-foundry-receipt.mjs |
Sanitized aggregate receipt; no code/repo/prompt content | Sarthak |
Privacy-safe product funnel
CodeVetter’s product contract is local-first, no telemetry (see the “No telemetry” badge on the landing hero). The funnel is therefore defined as evidence that can be collected without transmitting reviewed code, repository content or identity, prompts, findings, file paths, user API keys, or local database contents.
| Stage | Evidence | Source | Privacy stance |
|---|---|---|---|
| Acquisition | Landing page views, agent-indexing surface reachability | Cloudflare Pages analytics (aggregate, no review payload) | OK — no product content |
| Download intent | GitHub Release asset download counts + appcast.xml poll count |
GitHub Releases API (aggregate counts) | OK — no product content |
| Installation / update | Appcast version + EdDSA signature validity | appcast.xml (build-time, no user data) |
OK — no product content |
| First meaningful review | Not applicable centrally. Local SQLite local_reviews records status/duration; observability.rs aggregates locally |
Local only — never transmitted | N/A — would violate “no telemetry” |
| Meaningful return | Not applicable centrally. Local SQLite cc_sessions + local_reviews windowed counts |
Local only — never transmitted | N/A — would violate “no telemetry” |
Not-applicable decisions
Desktop activation/return tracking (2.2): Not applicable. The landing
page explicitly markets “No telemetry” as a product feature. Adding
centralized activation or return tracking would violate the product contract
and the CSP (connect-src 'self' https://api.codevetter.com https://api.github.com — and api.codevetter.com is unused by the desktop
app, reserved for landing proxy concerns). Local aggregate evidence stays in
SQLite; the user owns it.
Privacy-safe crash/failure evidence (2.3): Not applicable for central
transmission. local_reviews.error_message, repo_unpacked_reports.status,
and the get_agent_observability command already record version/build +
aggregate failure class locally. Transmitting failure classes centrally
would require a new egress path and a new analytics surface, which is out of
scope and against the product stance. The Foundry receipt (below) carries
only sanitized aggregate counts, never error text or paths.
Release contract
Every release candidate MUST pass before release approval:
| Gate | Workflow | Evidence |
|---|---|---|
| Lint + automation tests | ci.yml |
Biome, Knip, and Node contract tests green |
| Rust core, CLI, MCP | ci.yml |
cargo test, Clippy, rustfmt, and stdio lifecycle green |
| Native quiet lane | ci.yml / native-qualification.yml |
Swift package tests, offscreen render gates, Debug and Release compiles green |
| Package qualification | native-production-qualification.yml |
qualification.json with production identity, six signed companions, no coverage sections |
| Signing + notarization | native-production-qualification.yml |
Developer ID, Hardened Runtime, Library Validation, stapled notarization ticket |
| Installed upgrade proof | native-production-qualification.yml |
Isolated incumbent → native → rollback with stable-record continuity |
| Artifacts | release.yml |
CodeVetter-<version>-arm64.dmg, CodeVetter-<version>-arm64.zip, appcast.xml uploaded |
| Updater appcast | release.yml + scripts/verify-release-manifest.mjs |
Appcast HTTPS, EdDSA-signed, bound to the exact qualified ZIP; release-readiness.json reports shipping_ready: true |
Release approval remains explicit. Automation prepares evidence and MAY open a corrective PR, but MUST NOT publish a release or alter product direction without explicit approval. See runbooks/cut-a-release.md.
Updater appcast validation
scripts/verify-release-manifest.mjs validates that the live Sparkle
appcast.xml references a resolvable, signed release archive — without
publishing a release. It is safe to run from any branch. It checks:
appcast.xmldownloads from the latest-release endpoint.- The newest item carries a semver-shaped version.
- The item declares an archive URL that resolves (HTTP 200) to a real release asset.
- The enclosure carries a non-empty Sparkle EdDSA signature.
It does NOT download the full artifact, verify the signature against the pubkey, or touch the release pipeline. Those are release-time concerns.
Scheduled canary freshness contract
weekly.yml runs every Monday 09:00 UTC and on manual dispatch. It MUST
expose:
| Field | Source |
|---|---|
| Last run timestamp | GitHub Actions run metadata |
| Success / failure | Job conclusion |
| Bounds | timeout-minutes: 20 (declared in the workflow) |
| Timeout | The job is killed if it exceeds timeout-minutes |
| Source revision | git rev-parse HEAD recorded in the job summary + canary-evidence.json |
| Freshness | Days since the last successful run, computed against the declared cron interval |
| Unresolved failure evidence | The previous failed run’s conclusion + URL, if any |
The canary is not a release gate and not a deploy trigger. It is a coarse “is anything obviously broken” signal. If it misses its freshness window (no successful run within 8 days of the cron interval), Foundry reports it stale and does not infer desktop health.
Foundry handoff contract
scripts/emit-foundry-receipt.mjs produces a sanitized aggregate receipt
for Foundry. The receipt contains ONLY:
project_slug(fromfoundry.json)generated_at(ISO timestamp)git_revision(main HEAD short SHA)desktop_version(fromtauri.conf.json)ci_green(boolean — latestci.ymlconclusion on main)weekly_canary(object — last run timestamp, conclusion, freshness days)latest_release(object — tag, published_at, asset count, manifest valid)landing_live(boolean —https://codevetter.comreturns 200)
The receipt MUST NOT contain: reviewed code, diffs, file paths, repository
identity, prompts, findings, API keys, error message text, local database
contents, or any user-identifiable information. The emitter loads only
public metadata (git revision, tauri version, GitHub Actions status via
gh, live landing HTTP status). A unit test (scripts/emit-foundry-receipt.test.mjs)
proves that sensitive fixture inputs cannot appear in the receipt output.
Production release and production deploy remain explicit-approval actions; the receipt reports readiness, it does not trigger anything.
Current baseline (2026-07-19)
| Field | Value |
|---|---|
| Main HEAD | 92bb774 (seo: include docs in landing sitemap #34) |
| Desktop version | 1.2.22 (tauri.conf.json) |
| Latest release | v1.2.22 (2026-07-18T11:39:30Z) |
| Updater manifest | latest.json → v1.2.22/CodeVetter_aarch64.app.tar.gz (resolves, signature present) |
| Live landing | https://codevetter.com → 200 (Cloudflare HIT) |
| Latest CI | ci.yml run 29685994929 — success — 6m31s (2026-07-19) |
| Latest weekly canary | weekly.yml run 29247674529 — success — 16s (2026-07-13) |
| Canary freshness | 6 days since last success (within the 8-day window) |
Out of scope
- No new analytics vendor.
- No server-side review pipeline.
- No automatic production release.
- No user-code collection, credential handling, or product feature work.
- No change to review behavior, CSP, or the “No telemetry” product stance.