tensorfs 0.3.74__tar.gz → 0.3.75__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tensorfs-0.3.74 → tensorfs-0.3.75}/Cargo.lock +2 -2
- {tensorfs-0.3.74 → tensorfs-0.3.75}/Cargo.toml +1 -1
- {tensorfs-0.3.74 → tensorfs-0.3.75}/PKG-INFO +1 -1
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/main.rs +13 -1
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/err.rs +1 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/http.rs +51 -9
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/mod.rs +1 -1
- tensorfs-0.3.75/crates/tensorfs-core/tests/hub_tls.rs +124 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/pyproject.toml +1 -1
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/_ext.pyi +1 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/errors.py +2 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/Cargo.toml +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/build.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/h3-swiglu-layout.md +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/optional-cache-backfill.md +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/resident-conversion.md +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/resident_conversion_profile.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/asset_update.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/b64.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/conform.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/ingest.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/rd.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/repo.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/cache_roots.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/canon.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/capability.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/catalog/lock.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/catalog.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/cbor.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/checkpoint.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/checkpoint_root.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/corpus.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/adoption.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/companion_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/estimate.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/graft_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/group_commit_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/history_cost_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/part_rows_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/progress.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/resume_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/retention.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived/roots.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/derived.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/descriptors.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/disk.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/dtype.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/durability.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/fetch.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/fill.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/fit.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/gc.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/header.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/home.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ids.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/convert.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/custody.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/fingerprint.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/h3_lora.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/journal.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/mod.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/narrow.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/preflight.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/routes/sdxl.routes.json +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/routes/sdxl.spec.json +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/routes.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/source.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/ingest/transaction.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/jcs.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/lib.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/limits.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/machine.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/manifest.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/meta.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/project.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/providers.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/read.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/receipt.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/reclaim.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/registry.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/relation.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/repo_cache/identity.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/repo_cache.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/repository.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/sha256.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/source_artifact.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/spec.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/staging.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/stats.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/storage.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/store.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/api.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/http_reuse_tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/hub.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/ledger.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/memory.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/pace.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/policy.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/prefix.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/pull.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/push.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/ranged.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/speculate.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/transport/tests.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/unsynced.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/src/vectors.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/additive_fields.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/anima_hf_profile.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/as_is.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/checkpoint_roots.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/civitai_sdxl_profile.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fd_budget.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fd_headroom.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fetch_url_progress.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fit.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/foreign_json.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/h3_lora.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/h3_swiglu.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/home.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/import_tree.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/instrument_profiles.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/liveness.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/qwen_image21_profile.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/read_plan.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/reclaim.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/reclaim_run.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/repo_cache.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/repo_store.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/resident_admission.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/routed_single_file.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/sha256_backends.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/sharded_cas.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/source_artifacts.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/source_download.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/source_plan.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/source_prefixes.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/source_preflight.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/staging.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/store_boundaries.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/tensor_schema.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/transfer_memory.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/trust_index.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/version.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/write_through.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/Cargo.toml +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/src/docs.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/src/errors.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/src/ingest.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/src/lib.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-py/src/store.rs +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/__init__.py +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/_derived_channel.py +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/_source_channel.py +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/_tensors.py +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/derived.py +0 -0
- {tensorfs-0.3.74 → tensorfs-0.3.75}/python/tensorfs/py.typed +0 -0
|
@@ -439,7 +439,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
|
439
439
|
|
|
440
440
|
[[package]]
|
|
441
441
|
name = "tensorfs-core"
|
|
442
|
-
version = "0.3.
|
|
442
|
+
version = "0.3.75"
|
|
443
443
|
dependencies = [
|
|
444
444
|
"fs2",
|
|
445
445
|
"libc",
|
|
@@ -454,7 +454,7 @@ dependencies = [
|
|
|
454
454
|
|
|
455
455
|
[[package]]
|
|
456
456
|
name = "tensorfs-py"
|
|
457
|
-
version = "0.3.
|
|
457
|
+
version = "0.3.75"
|
|
458
458
|
dependencies = [
|
|
459
459
|
"pyo3",
|
|
460
460
|
"tensorfs-core",
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
//! The ONE transport (tfs-048/tfs-049/tfs-050). The credential is `--credential-file` or
|
|
42
42
|
//! TFS_CREDENTIAL (`bearer <token>`, `worker <id> <token>`, or empty for anonymous), never
|
|
43
43
|
//! bare argv; a URL of `-` arrives on stdin. Flags: --hub <base> --lane --session --streams <n>
|
|
44
|
-
//! --streams-start <n> --timeout <s> --allow-hosts a,b,.c --allow-local --max-redirects <n
|
|
44
|
+
//! --streams-start <n> --timeout <s> --allow-hosts a,b,.c --allow-local --max-redirects <n>
|
|
45
|
+
//! --ca-file <pem> (a private hub's CA, trusted beside the webpki set).
|
|
45
46
|
//! `--streams` is the most objects in flight (default 128, memory-bounded); the walk starts
|
|
46
47
|
//! at `--streams-start` (default 16) and doubles while measured goodput follows.
|
|
47
48
|
//! `tfs fetch` reads and backfills the Store's bound repo cache between the local Store
|
|
@@ -202,6 +203,17 @@ fn accept_printed_ids(args: Vec<String>) -> Vec<String> {
|
|
|
202
203
|
|
|
203
204
|
fn main() -> ExitCode {
|
|
204
205
|
let (args, flags) = split_flags(std::env::args().skip(1).collect());
|
|
206
|
+
if let Some(path) = flag(&flags, "ca-file") {
|
|
207
|
+
let trusted = fs::read(path)
|
|
208
|
+
.map_err(|e| format!("IO_FAILED: read {path}: {e}"))
|
|
209
|
+
.and_then(|pem| {
|
|
210
|
+
tensorfs_core::transport::trust_roots(&pem).map_err(|r| format!("{r} ({path})"))
|
|
211
|
+
});
|
|
212
|
+
if let Err(refusal) = trusted {
|
|
213
|
+
eprintln!("REFUSED {refusal}");
|
|
214
|
+
return ExitCode::FAILURE;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
205
217
|
let args = accept_printed_ids(args);
|
|
206
218
|
let a: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
|
|
207
219
|
match a.as_slice() {
|
|
@@ -30,10 +30,11 @@
|
|
|
30
30
|
use crate::err::{refuse, Code, Refusal, Result};
|
|
31
31
|
use crate::transport::ledger::{Deadline, Ledger};
|
|
32
32
|
use crate::transport::policy::CheckedUrl;
|
|
33
|
+
use rustls::pki_types::pem::PemObject;
|
|
33
34
|
use rustls::pki_types::{CertificateDer, ServerName};
|
|
34
35
|
use std::io::{ErrorKind, Read, Write};
|
|
35
36
|
use std::net::TcpStream;
|
|
36
|
-
use std::sync::{Arc, Mutex};
|
|
37
|
+
use std::sync::{Arc, Mutex, OnceLock};
|
|
37
38
|
use std::time::{Duration, Instant};
|
|
38
39
|
|
|
39
40
|
const HEAD_MAX_BYTES: usize = 64 * 1024;
|
|
@@ -211,13 +212,35 @@ struct Idle {
|
|
|
211
212
|
wire: Wire,
|
|
212
213
|
}
|
|
213
214
|
|
|
215
|
+
/// Authorities this process trusts beside the webpki set: a private hub's CA, named by its
|
|
216
|
+
/// caller as a location (`tfs --ca-file`). Set once, before the first exchange.
|
|
217
|
+
static EXTRA_ROOTS: OnceLock<Vec<CertificateDer<'static>>> = OnceLock::new();
|
|
218
|
+
|
|
219
|
+
/// Trust the PEM certificates in `pem` for every client this process builds.
|
|
220
|
+
pub fn trust_roots(pem: &[u8]) -> Result<usize> {
|
|
221
|
+
let roots: Vec<_> = CertificateDer::pem_slice_iter(pem)
|
|
222
|
+
.collect::<std::result::Result<_, _>>()
|
|
223
|
+
.map_err(|e| Refusal {
|
|
224
|
+
code: Code::UNKNOWN_FORMAT,
|
|
225
|
+
detail: format!("not a PEM certificate bundle: {e}"),
|
|
226
|
+
})?;
|
|
227
|
+
let (usable, _) = rustls::RootCertStore::empty().add_parsable_certificates(roots.clone());
|
|
228
|
+
if roots.is_empty() || usable != roots.len() {
|
|
229
|
+
return refuse(Code::UNKNOWN_FORMAT, "holds no usable CA certificate");
|
|
230
|
+
}
|
|
231
|
+
EXTRA_ROOTS.set(roots).map_err(|_| Refusal {
|
|
232
|
+
code: Code::UNKNOWN_FORMAT,
|
|
233
|
+
detail: "this process already chose its trust roots".into(),
|
|
234
|
+
})?;
|
|
235
|
+
Ok(usable)
|
|
236
|
+
}
|
|
237
|
+
|
|
214
238
|
impl Client {
|
|
215
239
|
pub fn new() -> Client {
|
|
216
|
-
Client::with_extra_roots(&[])
|
|
240
|
+
Client::with_extra_roots(EXTRA_ROOTS.get().map_or(&[], Vec::as_slice))
|
|
217
241
|
}
|
|
218
242
|
|
|
219
|
-
///
|
|
220
|
-
/// self-signed authority; production callers pass none and trust the webpki set.
|
|
243
|
+
/// Trusts the webpki set plus `extra_roots`.
|
|
221
244
|
pub fn with_extra_roots(extra_roots: &[CertificateDer<'static>]) -> Client {
|
|
222
245
|
let mut roots = rustls::RootCertStore::empty();
|
|
223
246
|
roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
|
@@ -482,7 +505,9 @@ fn connect(
|
|
|
482
505
|
)
|
|
483
506
|
}
|
|
484
507
|
|
|
508
|
+
#[allow(clippy::too_many_arguments)]
|
|
485
509
|
fn tls_handshake(
|
|
510
|
+
host: &str,
|
|
486
511
|
sock: &mut TcpStream,
|
|
487
512
|
conn: &mut rustls::ClientConnection,
|
|
488
513
|
deadline: Deadline,
|
|
@@ -516,10 +541,18 @@ fn tls_handshake(
|
|
|
516
541
|
Ok(0) => return refuse(fail, "origin closed the connection mid-handshake"),
|
|
517
542
|
Ok(_) => {
|
|
518
543
|
advanced = Instant::now();
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
544
|
+
// A certificate or protocol verdict is this client's, and re-asking reaches
|
|
545
|
+
// it again: refused typed, never retried as weather. The alert goes out so
|
|
546
|
+
// the origin logs why.
|
|
547
|
+
if let Err(e) = conn.process_new_packets() {
|
|
548
|
+
let _ = conn.write_tls(sock);
|
|
549
|
+
return refuse(
|
|
550
|
+
Code::TLS_UNTRUSTED,
|
|
551
|
+
format!(
|
|
552
|
+
"{host}: TLS refused: {e}; a private hub names its CA with --ca-file"
|
|
553
|
+
),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
523
556
|
}
|
|
524
557
|
Err(e) if would_block(&e) => {
|
|
525
558
|
stream_verdict(judge, ledger, advanced, "TLS handshake")?;
|
|
@@ -1041,7 +1074,16 @@ pub fn send<'l>(
|
|
|
1041
1074
|
})?;
|
|
1042
1075
|
let mut sock = sock;
|
|
1043
1076
|
let mut conn = Box::new(conn);
|
|
1044
|
-
tls_handshake(
|
|
1077
|
+
tls_handshake(
|
|
1078
|
+
&checked.host,
|
|
1079
|
+
&mut sock,
|
|
1080
|
+
&mut conn,
|
|
1081
|
+
deadline,
|
|
1082
|
+
ledger,
|
|
1083
|
+
judge,
|
|
1084
|
+
opened,
|
|
1085
|
+
fail,
|
|
1086
|
+
)?;
|
|
1045
1087
|
Wire::Tls { sock, conn }
|
|
1046
1088
|
} else {
|
|
1047
1089
|
Wire::Plain(sock)
|
|
@@ -49,7 +49,7 @@ mod speculate;
|
|
|
49
49
|
mod tests;
|
|
50
50
|
|
|
51
51
|
pub use api::{api_get, fetch_prefix, probe_length, Prefix};
|
|
52
|
-
pub use http::Client;
|
|
52
|
+
pub use http::{trust_roots, Client};
|
|
53
53
|
pub use hub::{
|
|
54
54
|
closure, closure_all, credential_from_spec, presign, Anonymous, Closure, CredentialProvider,
|
|
55
55
|
HostToken, Presigned, ScopedHeaders,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//! A hub whose certificate this machine does not trust is a verdict, not weather: `tfs fetch`
|
|
2
|
+
//! refuses it typed on the first handshake, and `--ca-file` names the private CA that makes
|
|
3
|
+
//! the same hub reachable.
|
|
4
|
+
|
|
5
|
+
use std::io::{Read, Write};
|
|
6
|
+
use std::net::{SocketAddr, TcpListener, TcpStream};
|
|
7
|
+
use std::process::Command;
|
|
8
|
+
use std::sync::{mpsc, Arc};
|
|
9
|
+
|
|
10
|
+
const ENVELOPE: &str =
|
|
11
|
+
r#"{"error":{"code":"checkpoint_not_found","message":"no such checkpoint"}}"#;
|
|
12
|
+
|
|
13
|
+
/// A loopback hub under a self-signed authority that answers every call it can read with a
|
|
14
|
+
/// typed 404. Every accepted peer is reported before its handshake.
|
|
15
|
+
fn private_hub() -> (u16, String, mpsc::Receiver<SocketAddr>) {
|
|
16
|
+
let key = rcgen::generate_simple_self_signed(vec!["127.0.0.1".into()]).unwrap();
|
|
17
|
+
let cert = rustls::pki_types::CertificateDer::from(key.cert.der().to_vec());
|
|
18
|
+
let private = rustls::pki_types::PrivateKeyDer::try_from(key.key_pair.serialize_der())
|
|
19
|
+
.unwrap()
|
|
20
|
+
.clone_key();
|
|
21
|
+
let config = rustls::ServerConfig::builder_with_provider(Arc::new(
|
|
22
|
+
rustls::crypto::ring::default_provider(),
|
|
23
|
+
))
|
|
24
|
+
.with_safe_default_protocol_versions()
|
|
25
|
+
.unwrap()
|
|
26
|
+
.with_no_client_auth()
|
|
27
|
+
.with_single_cert(vec![cert], private)
|
|
28
|
+
.unwrap();
|
|
29
|
+
let config = Arc::new(config);
|
|
30
|
+
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
|
31
|
+
let port = listener.local_addr().unwrap().port();
|
|
32
|
+
let (peers, accepted) = mpsc::channel();
|
|
33
|
+
std::thread::spawn(move || {
|
|
34
|
+
for socket in listener.incoming() {
|
|
35
|
+
let Ok(socket) = socket else { return };
|
|
36
|
+
let _ = peers.send(socket.peer_addr().unwrap());
|
|
37
|
+
let conn = rustls::ServerConnection::new(Arc::clone(&config)).unwrap();
|
|
38
|
+
let mut stream = rustls::StreamOwned::new(conn, socket);
|
|
39
|
+
let mut head = Vec::new();
|
|
40
|
+
let mut chunk = [0u8; 4096];
|
|
41
|
+
while !head.windows(4).any(|w| w == b"\r\n\r\n") {
|
|
42
|
+
match stream.read(&mut chunk) {
|
|
43
|
+
Ok(n) if n > 0 => head.extend_from_slice(&chunk[..n]),
|
|
44
|
+
_ => break,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if head.windows(4).any(|w| w == b"\r\n\r\n") {
|
|
48
|
+
let answer = format!(
|
|
49
|
+
"HTTP/1.1 404 Not Found\r\ncontent-type: application/json\r\ncontent-length: {}\r\nconnection: close\r\n\r\n{ENVELOPE}",
|
|
50
|
+
ENVELOPE.len()
|
|
51
|
+
);
|
|
52
|
+
let _ = stream.write_all(answer.as_bytes());
|
|
53
|
+
stream.conn.send_close_notify();
|
|
54
|
+
let _ = stream.flush();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
(port, key.cert.pem(), accepted)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// How many connections reached the hub before this call: a sentinel connection is accepted
|
|
62
|
+
/// after every one queued ahead of it.
|
|
63
|
+
fn connections(port: u16, accepted: &mpsc::Receiver<SocketAddr>) -> usize {
|
|
64
|
+
let sentinel = TcpStream::connect(("127.0.0.1", port)).unwrap();
|
|
65
|
+
let mine = sentinel.local_addr().unwrap();
|
|
66
|
+
accepted.iter().take_while(|peer| *peer != mine).count()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fn fetch(root: &std::path::Path, port: u16, extra: &[&str]) -> (bool, String) {
|
|
70
|
+
let out = Command::new(env!("CARGO_BIN_EXE_tfs"))
|
|
71
|
+
.args(["fetch", root.to_str().unwrap(), "proof/model"])
|
|
72
|
+
.args(["--hub", &format!("https://127.0.0.1:{port}")])
|
|
73
|
+
.args(extra)
|
|
74
|
+
.env("TFS_CREDENTIAL", "")
|
|
75
|
+
.output()
|
|
76
|
+
.unwrap();
|
|
77
|
+
(
|
|
78
|
+
out.status.success(),
|
|
79
|
+
String::from_utf8_lossy(&out.stderr).into_owned(),
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[test]
|
|
84
|
+
fn an_untrusted_hub_is_refused_once_and_a_named_ca_reaches_it() {
|
|
85
|
+
let dir = std::env::temp_dir().join(format!("tfs-hub-tls-{}", std::process::id()));
|
|
86
|
+
let _ = std::fs::remove_dir_all(&dir);
|
|
87
|
+
std::fs::create_dir_all(&dir).unwrap();
|
|
88
|
+
let root = dir.join("store");
|
|
89
|
+
let init = Command::new(env!("CARGO_BIN_EXE_tfs"))
|
|
90
|
+
.args(["store", "init", root.to_str().unwrap()])
|
|
91
|
+
.output()
|
|
92
|
+
.unwrap();
|
|
93
|
+
assert!(
|
|
94
|
+
init.status.success(),
|
|
95
|
+
"{}",
|
|
96
|
+
String::from_utf8_lossy(&init.stderr)
|
|
97
|
+
);
|
|
98
|
+
let (port, pem, accepted) = private_hub();
|
|
99
|
+
|
|
100
|
+
let (ok, stderr) = fetch(&root, port, &[]);
|
|
101
|
+
assert!(
|
|
102
|
+
!ok && stderr.contains("REFUSED TLS_UNTRUSTED") && stderr.contains("127.0.0.1"),
|
|
103
|
+
"{stderr}"
|
|
104
|
+
);
|
|
105
|
+
assert_eq!(
|
|
106
|
+
connections(port, &accepted),
|
|
107
|
+
1,
|
|
108
|
+
"an untrusted hub was asked again: {stderr}"
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
let ca = dir.join("hub-ca.pem");
|
|
112
|
+
std::fs::write(&ca, pem).unwrap();
|
|
113
|
+
let (ok, stderr) = fetch(&root, port, &["--ca-file", ca.to_str().unwrap()]);
|
|
114
|
+
assert!(
|
|
115
|
+
!ok && stderr.contains("REFUSED REF_NOT_FOUND") && stderr.contains("checkpoint_not_found"),
|
|
116
|
+
"{stderr}"
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
let garbage = dir.join("garbage.pem");
|
|
120
|
+
std::fs::write(&garbage, "not a certificate").unwrap();
|
|
121
|
+
let (ok, stderr) = fetch(&root, port, &["--ca-file", garbage.to_str().unwrap()]);
|
|
122
|
+
assert!(!ok && stderr.contains("REFUSED UNKNOWN_FORMAT"), "{stderr}");
|
|
123
|
+
let _ = std::fs::remove_dir_all(&dir);
|
|
124
|
+
}
|
|
@@ -278,6 +278,7 @@ class StoreEra(Refusal): ...
|
|
|
278
278
|
class StoreRootAbsent(Refusal): ...
|
|
279
279
|
class SweepSetIncomplete(Refusal): ...
|
|
280
280
|
class TensorSchemaMismatch(Refusal): ...
|
|
281
|
+
class TlsUntrusted(Refusal): ...
|
|
281
282
|
class TotalBytesCap(Refusal): ...
|
|
282
283
|
class TotalRefsCap(Refusal): ...
|
|
283
284
|
class TrailingBytes(Refusal): ...
|
|
@@ -149,6 +149,7 @@ from ._ext import (
|
|
|
149
149
|
StoreRootAbsent,
|
|
150
150
|
SweepSetIncomplete,
|
|
151
151
|
TensorSchemaMismatch,
|
|
152
|
+
TlsUntrusted,
|
|
152
153
|
TotalBytesCap,
|
|
153
154
|
TotalRefsCap,
|
|
154
155
|
TrailingBytes,
|
|
@@ -306,6 +307,7 @@ __all__ = [
|
|
|
306
307
|
"StoreRootAbsent",
|
|
307
308
|
"SweepSetIncomplete",
|
|
308
309
|
"TensorSchemaMismatch",
|
|
310
|
+
"TlsUntrusted",
|
|
309
311
|
"TotalBytesCap",
|
|
310
312
|
"TotalRefsCap",
|
|
311
313
|
"TrailingBytes",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/optional-cache-backfill.md
RENAMED
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/examples/resident_conversion_profile.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor
RENAMED
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json
RENAMED
|
File without changes
|
{tensorfs-0.3.74 → tensorfs-0.3.75}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|