This project uses a Cargo-first vendoring model:
- Cargo remains the resolver, lockfile authority, and build system.
- Vendored source is owned in
nikivdev/flow-vendor. flowpins vendored state by commit invendor.lock.toml.flowuses[patch.crates-io]path overrides intolib/vendor/*.
This gives direct dependency control without giving up Cargo behavior.
- crates.io + transitive dependency growth hurts compile times and iteration speed.
- upstream crates can pull convenience dependencies, macros, and features we do not need.
- editing third-party code in-place inside the main repo pollutes history and makes updates hard.
- keep Cargo benefits (resolver correctness, lock semantics, ecosystem compatibility),
- gain direct control over dependency source and shape,
- keep upstream sync fast and automatable,
- keep repository history readable.
- dependency source churn lives in
flow-vendor, - application-level pin and wiring lives in
flow, - updates are reproducible and lock-pinned,
- trim/refactor opportunities are local and fast.
This model borrows the parts of Nix that matter most for dependency control:
- pinned inputs (
vendor.lock.toml,Cargo.lock), - deterministic materialization (
vendor-repo.sh hydrate), - provenance/checksum verification (
vendor-manifest, strict verify), - transactional updates with rollback safety (
vendor-control.sh inhouse), - closure-size reduction by trimming unused dependency surface.
Reference:
docs/vendor-nix-inspiration.md
- Faster local iteration by removing unneeded dependency surface area.
- Ability to aggressively trim crates to exactly what
flowuses. - Deterministic hydration in CI and local environments from a pinned vendor commit.
- Clean
flowhistory: metadata/pins inflow, source churn inflow-vendor. - Upstream updates remain scriptable and reviewable.
vendor.lock.toml- Source of truth for vendor remote, branch, checkout, pinned commit, and crate map.
Cargo.toml[patch.crates-io]points selected crates tolib/vendor/<crate>.
Cargo.lock- Must resolve vendored crates by path (no registry source for vendored entries).
lib/vendor/<crate>- Materialized source tree used by Cargo path patches.
lib/vendor-manifest/<crate>.toml- Per-crate metadata for version/provenance/sync and verification.
scripts/vendor/*- Toolkit for inhouse, hydrate, status, sync, and vendor-repo operations.
- owns pins, manifests, trim logic hooks, and Cargo wiring.
- should not include full vendored source history churn.
- canonical storage for vendored crate source (
crates/<crate>), - vendored crate manifests (
manifests/<crate>.toml), - profile metadata used during hydration.
Do not replace Cargo. Use Cargo as the system of record:
- resolve versions through
Cargo.lock, - use
cargo update -p <crate> --precise <version>for deterministic lock rewrites, - build and validate with normal Cargo commands (
cargo check,cargo test --no-run), - use vendoring only as controlled source substitution via patches.
Recommended entrypoint:
~/code/rise/scripts/vendor-control.sh inhouse --project ~/code/flow <crate> [version]What this does:
- Ensures lock entry and Cargo patch wiring.
- Materializes crate from Cargo cache into
lib/vendor/<crate>. - Stores crate history in
lib/vendor-history/<crate>.git. - Writes
lib/vendor-manifest/<crate>.toml+UPSTREAM.toml. - Re-syncs
Cargo.lockto exact vendored version. - Applies trim hooks (
scripts/vendor/apply-trims.sh). - Imports local materialized source into
.vendor/flow-vendor. - Pins
vendor.lock.tomlto new vendor commit.
Run after each vendoring step:
f update-deps --important
f vendor-trims
~/code/rise/scripts/vendor-control.sh verify --project ~/code/flow
python3 ./scripts/vendor/rough_edges_audit.py --project . --strict-warnings
cargo check -q
scripts/vendor/sync-all.sh --important --dry-runFor full dependency refresh (latest allowed by policy), run:
f update-depsUseful flags:
f update-deps --dry-run
f update-deps --no-major
f update-deps --push-vendorverify enforces:
- crate exists in
vendor.lock.toml, - crate exists in
Cargo.lock, - no registry source for vendored crate in
Cargo.lock, - one resolved version per vendored crate,
- patch path matches lock materialized path,
- manifest version matches lock version.
vendor-rough-audit --strict-warnings additionally enforces warning-hygiene
regressions for known vendored crate hot spots (crossterm, portable-pty,
x25519-dalek, ratatui) so release builds stay quiet.
inhouse now records provenance fields in crate manifests:
registry_indexcargo_registry_checksumcrate_archive_sha256checksum_matchupstream_repositoryupstream_homepagehistory_head
Use report mode:
~/code/rise/scripts/vendor-control.sh provenance --project ~/code/flowUse stricter mode when migrating fully:
~/code/rise/scripts/vendor-control.sh verify --project ~/code/flow --strict-provenancevendor-control.sh inhouse includes rollback protection by default:
- snapshot relevant files before mutation,
- on failure, restore pre-run
Cargo.toml,Cargo.lock,vendor.lock.toml, - remove newly created manifest/source/history artifacts for failed crate,
- restore prior vendor lock pin.
Escape hatch (not recommended except debugging):
~/code/rise/scripts/vendor-control.sh inhouse --project ~/code/flow <crate> --no-rollbackTrack updates:
scripts/vendor/check-upstream.sh --important
scripts/vendor/sync-all.sh --important --dry-runApply updates intentionally:
scripts/vendor/sync-all.sh --important
scripts/vendor/vendor-repo.sh import-local
git -C .vendor/flow-vendor push origin mainPolicy:
- patch updates can be frequent,
- minor/major updates happen in explicit review windows (
--allow-minor,--allow-major).
To make vendored code practical at scale, we index first-party + vendored sources into Typesense and query them fast during refactors and trim work.
This follows the same high-level pattern as opensrc:
- keep a local source inventory (
.vendor/typesense/sources.json), - keep local source materialized (already done by vendor hydrate/inhouse),
- index/search against local code state, not remote assumptions.
Flow entrypoints:
f vendor-typesense-setup # one-time if Typesense is not installed locally
f vendor-typesense-up
f vendor-code-index
f vendor-code-search "Router"
f vendor-code-search "serde" --scope vendor --crate axum
f vendor-code-search-sources "ratatui"Script used by tasks:
python3 ./scripts/vendor/typesense_code_index.py --helpDesign goals:
- search by vendored crate boundary (
--crate <name>), - search by ownership boundary (
--scope vendor|firstparty), - keep source provenance in inventory (
version,checksum,history_head), - make trim/upstream update work faster by removing "where is this code?" overhead.
Reference:
docs/vendor-code-intelligence.mdfor architecture, commands, and operating loop.
CI must hydrate vendored source from vendor.lock.toml before Cargo build:
scripts/vendor/vendor-repo.sh hydrateAny CI build skipping hydrate can fail with missing lib/vendor/* path deps.
For each vendored crate:
- inspect real usage in
flow(APIs/types called), - remove optional features not used,
- delete convenience-only dependencies,
- remove proc-macro convenience layers where reasonable,
- reduce duplicate major versions where possible,
- keep trim hooks deterministic and replayable.
Use:
scripts/vendor/offenders.sh
cargo tree -dto rank impact and watch duplicate-version pressure.
Operational tooling for this loop:
f vendor-rough-auditf vendor-offendersf vendor-bench-iter -- --mode incremental --samples 3f vendor-optimize-loop
Reference:
docs/vendor-optimization-loop.md
- In
flow: commit only lock/manifest/patch/docs/script changes. - In
flow-vendor: commit source churn. - Push
flow-vendorfirst, then pushflowpin updates. - Prefer one crate per commit for auditability.
Inspect state:
scripts/vendor/vendor-repo.sh statusRe-hydrate local materialization from pinned commit:
scripts/vendor/vendor-repo.sh hydrateRe-pin to known commit:
scripts/vendor/vendor-repo.sh pin <commit>No. Cargo remains central. Vendoring is an ownership layer on top.
To keep main repo history focused on product changes while retaining full dependency source control.
Yes. check-upstream + sync-* + locked import flow is designed for repeatable upstream ingestion.