probation 0.1.0

A filtering proxy for npm and PyPI that withholds packages until they are eligible.
docs.rs failed to build probation-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

probation

crates.io

Open-source package firewall for npm and PyPI.

A self-hosted registry proxy that hides releases younger than a configured delay and hides known-malicious packages and artifacts. npm and pip keep doing the dependency resolution; this decides what there is to resolve against, and verifies every artifact before delivering it.

The problem it addresses: a compromised package can be installed the moment it is published, before any malware feed has seen it. Blocking only known-bad releases leaves that window open, and simply refusing a new download breaks installs that an older compatible release would have satisfied. So the firewall withholds the young release and lets the client resolve to an older eligible one — without anyone editing a requirement.

Eligible means "passed the configured checks". It is not a claim that a package is harmless.

Quick start

From crates.io (needs the build tools listed under Building and testing):

cargo install probation --locked
probation check-config config.sample.toml

or from a checkout:

cargo build --release --locked
./target/release/probation check-config config.sample.toml
./target/release/probation serve --config /etc/probation/config.toml

or from the container image:

docker build -t probation:mvp .
docker run -d -p 127.0.0.1:8080:8080 \
  -v /srv/probation:/var/lib/probation \
  probation:mvp serve --config /etc/probation/config.toml

Point clients at it:

# .npmrc
registry=https://packages.example.org/npm/
audit=false
# pip.conf
[global]
index-url = https://packages.example.org/pypi/simple/

config.sample.toml and blocklist.sample.json in this repository are the shapes those two files take. Read docs/operations.md before running this for real — in particular section 3, because cache_max_bytes does not bound the state database, and section 6, because per-client rate limiting is the reverse proxy's job and not this service's.

What it does not do

It enforces on delivery, so packages already installed or already in a client's own cache are outside its reach, as are alternate indexes, Git and URL dependencies, local wheels, and lockfiles pinning upstream URLs directly. It has no UI, no publishing, no private-registry federation, no vendor feed adapters, no archive scanning and no administrative API. The blocklist is produced by something else; this consumes one local JSON file.

docs/operations.md §7 and §12 are the complete lists.

Building and testing

cargo clippy --all-targets -- -D warnings
cargo test                                  # offline; no test reaches a public network
cargo test --test e2e_npm -- --ignored      # drives the real npm client
cargo test --test e2e_pip -- --ignored      # drives the real pip client
cargo bench                                 # the SPEC §12 measurements
cargo bench --bench delivery_rated_load     # ten minutes; the rated-load figure below

Building needs cmake, a C compiler and perl in addition to the Rust toolchain pinned by rust-toolchain.toml: reqwest's default rustls crypto provider is aws-lc-rs, which builds from C. The e2e tests additionally need npm, and python3 with pip, setuptools and build.

Benchmark results against the specification's acceptance targets — every one of them met, with the pre-change baseline kept alongside — are in docs/operations.md §10.

Rated load: the delivery pipeline sustains 59,288 decided requests/second with zero records lost, measured on the reference hardware named in docs/operations.md §8. The default queue budget is sized from a stated 200 requests/second reference load, not from that ceiling — §8 explains why and states what a default deployment's budget survives and how to compute your own tolerance.

Documents

docs/codebase-overview.md is the pre-implementation onboarding briefing and is stale: it was written before any source existed and still says so. It is not linked above for that reason.

Licensed under Apache-2.0; see LICENSE.