# Contributing to Shardline This guide defines how to contribute changes to `shardline` while keeping architecture, reliability, and release standards intact. ## Scope This repository is a Rust workspace with the main CLI crate at `crates/shardline` (published as `shardline`). Primary references: - Project overview and run commands: `README.md` - Docs index: `docs/README.md` - Architecture and boundaries: `docs/ARCHITECTURE.md` - Protocol contract: `docs/PROTOCOL_CONFORMANCE.md` - Security and invariants: `docs/SECURITY_AND_INVARIANTS.md` - Operations docs: `docs/OPERATIONS.md` ## Prerequisites - Rust stable toolchain - `cargo-make` (used by contributor quality gates) - Docker (for Docker-backed integration tests) - `kind`, `kubectl`, and Python 3 (for the disposable Kubernetes smoke test) Quick smoke check: ```bash cargo check -p shardline ``` ## Development workflow 1. Make focused changes in the owning crate or module. 2. Add or update tests with the behavior change. 3. Run contributor quality gates locally. 4. Open a PR with a clear summary, risk notes, and test evidence. ### PostgreSQL qualification Use a disposable database and export its connection string as `DATABASE_URL`. Apply the candidate's migrations before running the gate; a database migrated only by the preceding release is missing the candidate's frontend tables. ```bash cargo run --locked --all-features -p shardline -- db migrate up --database-url "$DATABASE_URL" cargo make test-postgres ``` The gate checks both v1.12.1 recovery and v1.11.3 preservation of newer evidence. It fetches checksum-pinned Linux x86_64 binaries when they are not supplied. To reuse local binaries or run on another platform, set `SHARDLINE_N_MINUS_ONE_BINARY` to a native v1.12.1 executable and `SHARDLINE_LEGACY_RECOVERY_BINARY` to a native v1.11.3 executable. These are distinct compatibility contracts; the historical binary does not replace the adjacent release. Remote object-store and stock-client qualification require their separately provisioned gates as well. ### Full Docker integration prerequisites `cargo make test-integration` also runs interrupted CLI storage-copy tests. Build the current CLI with `cargo build --locked --release -p shardline` and set `CARGO_BIN_EXE_shardline` to a frozen copy of that executable. Respect a custom `CARGO_TARGET_DIR` when locating the build output. Set `SHARDLINE_N_MINUS_ONE_BINARY` to the released v1.12.1 executable. The archive-history cases separately require `SHARDLINE_ARCHIVE_PREDECESSOR_BINARY`: a CLI built from development commit `a2f343963f0105e6c89fad8c6c76d150211c648a`, which produced the older temporary-directory task archives. This historical development fixture does not replace the released upgrade/rollback baseline. Use absolute paths and keep these executables unchanged throughout the run. Missing fixtures fail qualification; they must not be counted as passing tests. ### Distributed-integrity qualification Use Docker, Git, `libfaketime`, and a Python 3 environment with `huggingface_hub==2.2.0` and `hf_xet==1.7.0` on `PATH`. Run: ```bash SHARDLINE_FAKETIME_LIBRARY=/path/to/libfaketime.so.1 \ cargo make test-distributed-integrity /private/evidence/distributed ``` The gate freezes the current binary, verifies the released v1.12.1 baseline, and runs every deployment and multi-node test, including ignored qualification cases. Missing clients, skipped cases and failed assertions fail the gate. Keep evidence outside the checkout; logs can contain backend addresses. ### Disk-pressure qualification On Linux, run the candidate CLI against a disposable 512 MiB ext4 image with MinIO. The drill fills only that image, checks that failed uploads remain unpublished, frees space, retries the identical content, and restarts Shardline before checking every downloaded byte. It exercises both S3 and the stock `hf_xet` client, including its normal retry window. Requires Docker with privileged containers, `mkfs.ext4`, Python 3 with `boto3`, and a Python environment exposing `hf_xet.XetSession` (validated with 1.7.0). Pass a frozen candidate executable; do not rebuild or replace it during the drill. Use a new evidence directory outside the checkout for each run: ```bash cargo make test-disk-pressure /path/to/shardline /private/evidence/sqlite \ --metadata sqlite --native-python /path/to/xet-environment/bin/python cargo make test-disk-pressure /path/to/shardline /private/evidence/postgres \ --metadata postgresql --native-python /path/to/xet-environment/bin/python ``` The runner creates and removes its own database, MinIO containers and loop mount. Client logs stay private because upstream errors may contain signed URLs or credentials. Missing prerequisites and timeouts fail qualification. This is a bounded 1 MiB S3 / 9 MiB native-Xet recovery drill, not a throughput benchmark or proof of every client's behavior under disk pressure. ## Git commits and pull requests ### Philosophy - Commits are brief and atomic: one logical change, easy to scan. - Pull requests carry the full context: why, scope, testing, and impact. ### Commit message format Use one of: - `: ` - `(): ` (optional scope, e.g. `server`, `storage`, `protocol`, `ci`, `docs`) Examples: - `feat(cli): add config check command` - `fix(server): reject ambiguous signing key input` - `chore(ci): run dependency policy checks` - `docs(deployment): clarify host-native startup` - `refactor(index): extract lifecycle state reader` Supported types: - `docs` documentation - `feat` new feature - `fix` bug fix - `refactor` code restructuring - `test` test changes - `chore` build, CI, dependencies, tooling - `perf` performance changes Subject rules: - Imperative mood (`add`, `fix`, `refactor`) - Lowercase start (except proper nouns) - No trailing period - Aim for <= 50 characters - Be specific, not generic Key rule: - Keep commit titles short and scannable. - Put detailed rationale and impact in the PR description, not in commit titles. ### Pull request title format Use: - `: — ` - Optional scope is allowed: `(): — ` Examples: - `feat(cli): add providerless setup validation — reduces bootstrap mistakes` - `fix(server): reject conflicting signing key sources — hardens startup safety` - `docs(deployment): simplify host run path — reduces operator confusion` ### Pull request description requirements PRs must include: - Description: what changed and why it matters. - Changes: concrete list of file/module changes. - Motivation: business and technical reasons; alternatives considered if relevant. - Scope and impact: affected crates, compatibility, operational impact. - Testing: what was run and what scenarios were validated. - Related docs/issues: docs updated, issue references, release or rollout notes when relevant. For cross-crate, protocol, or deployment-impacting changes: - Explicitly list affected crates (`shardline-protocol`, `shardline-storage`, `shardline-index`, `shardline-cas`, `shardline-cache`, `shardline-vcs`, `shardline-server`, `shardline`). - Explain cross-crate interaction changes. - Note protocol, migration, or rollback implications if any. - Call out security or operator impact when behavior changes at runtime boundaries. Reference template: - `.github/pull_request_template.md` ## Issues ### Issue title format Use the same title shape as PRs wherever possible: - `: — ` - Optional scope is allowed: `(): — ` Examples: - `fix(storage): local root symlink race on startup — can escape deployment root` - `feat(cli): add backup manifest diff mode — simplifies restore validation` - `refactor(server): split provider bootstrap wiring — reduces app.rs churn` Supported issue types follow the same repository vocabulary: - `fix` - `feat` - `docs` - `refactor` - `test` - `chore` - `perf` ### Issue body requirements Issues should include: - Description: what is wrong or what should change. - Current behavior or gap. - Expected behavior or requested outcome. - Scope and impact: affected crates, deployments, operators, or clients. - Reproduction or validation evidence when filing bugs. - Related docs or prior issues. Reference templates: - `.github/ISSUE_TEMPLATE/bug_report.md` - `.github/ISSUE_TEMPLATE/feature_request.md` - `.github/ISSUE_TEMPLATE/maintenance_task.md` ## Required local checks before PR Run: ```bash cargo make ci ``` This includes: - formatting check - clippy across the workspace - nextest across the workspace - release binary packaging smoke test - dependency audit Run infrastructure coverage when changing Docker-backed storage, service lifecycle, or Kubernetes deployment behavior: ```bash cargo make test-docker cargo make test-kubernetes ``` To run both sequentially (Docker coverage first, then the disposable `kind` cluster): ```bash cargo make test-infrastructure ``` `test-kubernetes` creates and deletes a local `kind` cluster and image; it preserves diagnostics only when the smoke test fails. For dependency-policy checks too: ```bash cargo make ci-full ``` Coverage uses LLVM source-based instrumentation. Generate a machine-readable summary and enforce the checked-in non-regression ratchet with: ```bash cargo make coverage-check ``` Use `cargo make coverage-html` for the local HTML report. ## Architecture and code rules Follow the current project constraints: - Keep crate boundaries intentional: `shardline-protocol`, `shardline-storage`, `shardline-index`, `shardline-cache`, `shardline-cas`, `shardline-vcs`, `shardline-server`, and `shardline` should keep their current responsibilities clear. - Keep public contracts explicit and type-driven. - Prefer validated constructors and domain newtypes for invariants. - Use typed enum errors (`thiserror`) instead of stringly error categories. - Keep security-sensitive filesystem, protocol, and token logic fail-closed. - Prefer declaration and re-export only in `mod.rs`. Reference docs: - `docs/ARCHITECTURE.md` - `docs/PROTOCOL_CONFORMANCE.md` - `docs/SECURITY_AND_INVARIANTS.md` ## Testing expectations - For behavior changes, update or add tests that fail before the fix and pass after. - Every bug fix should include a regression test. - Keep tests deterministic and fast. - If you touch protocol parsing, lifecycle repair, storage boundaries, or token flows, expand edge-case coverage. Benchmark workflow for hot-path changes: - Use `cargo make shardline-bench-protocol` for protocol microbenchmarks. - Use `cargo make shardline-bench-local-backend` for local-backend hot paths. - Use `cargo make shardline-bench-e2e` or `cargo make shardline-bench-ingest` when changing end-to-end or ingest-critical behavior. - Treat benchmark deltas as evidence, not proof by themselves: explain workload shape and limits in the PR. Fuzzing workflow: - Fuzz targets and corpora are in `crates/fuzz/`. - Run bounded fuzz smoke locally with `cargo make shardline-fuzz-smoke`. - Replay every checked-in corpus deterministically with `cargo make shardline-fuzz-regression`. - For deeper campaigns, run `bash scripts/shardline/fuzz.sh run ` or use the underlying `cargo fuzz` workflow from `crates/fuzz/` if needed. - When fuzz finds a crash, reproduce it, then add: - a deterministic regression test in the owning module, and - a minimized corpus seed in the owning fuzz corpus. ## Observability and operability requirements For operationally significant changes: - Add or update structured logs, metrics, and traces with stable fields. - Keep telemetry lightweight on hot paths. - Update docs when behavior, config, rollout shape, or operator procedure changes. References: - `docs/OPERATIONS.md` - `docs/DEPLOYMENT.md` - `docs/SYSTEMD.md` - `docs/k8s/README.md` ## CI and release notes - PRs run CI via `.github/workflows/ci.yml`. - Release checks and publish are handled by `.github/workflows/release.yml`. - Release publishes are driven from version tags and publish the internal crate graph in dependency order before the `shardline` CLI crate. ## PR checklist Before requesting review, confirm: - [ ] `cargo make ci` passes locally - [ ] tests cover new behavior and regressions - [ ] crate boundaries and runtime invariants are preserved - [ ] docs are updated if behavior, config, or operations changed - [ ] performance impact is documented when relevant - [ ] security implications are documented when relevant