4 Commits

Author SHA1 Message Date
32c8a3c2b5 test(conformance): stop disabling Xet, so the fallback is actually tested
All checks were successful
ci / web (push) Successful in 1m41s
ci / check (push) Successful in 6m40s
The suite set `HF_HUB_DISABLE_XET=1` in the client environment. That is not
a configuration anyone runs: `hf_xet` installs as a `huggingface_hub`
dependency, so a real user's client is Xet-capable whether they asked for
it or not. Every conformance run so far has therefore been proving
something about a client with Xet switched off by the harness, and nothing
at all about the one rustingface has to work with.

That matters more than it sounds. Downstream Xet behaviour is half of spec
§8 and it is the half exposed to the Hub's migration: rustingface
implements no Xet, so the whole "point HF_ENDPOINT at it and everything
works" claim rests on a Xet-capable client *choosing* HTTP. That choice was
untested.

Stop disabling it, and add a check that asserts the choice from inside the
client rather than by inspecting our own headers -- the question is not
which headers we sent but what the client concluded from them. It refuses
to pass vacuously: if `hf_xet` is absent it fails loudly rather than
quietly proving nothing, which is how the harness's own opt-out was found.

The full suite passes with Xet enabled, 12 checks. So the posture in spec §8
holds against a real client, and now says so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqNtYNhov3fukx46KS9R7L
2026-09-02 15:06:17 +03:00
cfa53e14bd fix(data): a hidden 30s body timeout capped every proxied blob
`object_store` puts a 30-second `reqwest` timeout on the whole request,
body included. On a proxied blob that is not a timeout at all: the bucket
is read at the pace the client drains it, so it is a maximum servable
file size.

The reason it never looked like one is that object_store hides its own
consequences. It catches every response-body error and silently retries
with a resumed Range, so a large read does not fail at 30s -- it
reconnects every 30s and keeps going, until RetryConfig's 180s
retry_timeout is spent. Then the body simply ends, with a 200 already on
the wire and nothing logged anywhere. The ceiling is 180s x bandwidth: at
the 8MB/s a GPU host gets to caveman, no file over ~1.4GB can ever be
served, and no client retry converges because the next attempt is no
faster. Measured against the live bucket, 500MiB at 1MB/s: cut at 184.1s,
193,340,351 of 524,288,000 bytes. With the timeout disabled, 499.6s and
complete -- the same wall time curl takes reading the same object
straight from MinIO.

Disable it, and guard the stream the way a stream should be guarded:
`storage.connect_timeout` and an idle `storage.read_timeout` that bounds
silence rather than progress. A test asserts the total cap stays off.

Issue #1 named `server.request_timeout` as the cause. It was not -- that
key was parsed and then read by nothing, which is its own problem and is
why the hunt started 300 seconds away from a 180-second bug. Remove it.

Also log when a blob response ends before its Content-Length. Once the
headers are out the bytes leave through hyper, so a cut mid-body was
invisible on this side: the service logged a clean 200 while the client
saw a short read and retried forever.

Refs #1

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqNtYNhov3fukx46KS9R7L
2026-09-02 13:03:34 +03:00
059c781422 fix(conformance): the hf CLI check was silently skipping in CI
All checks were successful
deploy / build-web (push) Successful in 1m42s
deploy / build (push) Successful in 6m37s
deploy / deploy (push) Successful in 18s
deploy / deploy-web (push) Successful in 10s
The suite's first run on a runner reported "10 passed, 0 failed" and
exited 0. Locally it is 11. The difference is the `hf` CLI check, which
did not run: the workflow invokes .venv/bin/python directly without
putting the venv's bin on PATH, so shutil.which("hf") found nothing and
the check skipped.

A skipped check reads exactly like a passing one, and this is the suite
that runs unattended on a weekly timer specifically to notice when a
client changes underneath us -- so a silent skip defeats its purpose.

Exports the venv's bin in the workflow and asserts `hf version` before
the suite, so a missing CLI fails the job outright rather than being
quietly stepped over. Also counts skips and lists them in the summary,
where they cannot be mistaken for passes.

Verified both ways: with the venv off PATH the suite now reports
"10 passed, 0 failed, 1 skipped" and names it; with it on PATH, 11
passed and 0 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XZG2i4AmfSqE97EJGBVb64
2026-08-31 14:14:15 +03:00
cb1ca8b6af feat(rustingface): implement the registry, admin CLI and deployment
Some checks failed
deploy / build (push) Waiting to run
deploy / deploy (push) Has been cancelled
Scaffolds the workspace per architecture/generic.md §1 and implements
phases 0-3 of doc/spec.md §12.

Crates:
  entities  manifest/ref/repo schemas, bucket key layout, config, the
            X-Error-Code taxonomy. No I/O.
  core      resolver, freeze pinning, single-flight, the streaming tee,
            policy, gc/verify/refresh. Defines the Store and Upstream
            ports.
  data      object_store (S3 + local) and reqwest Hub adapters.
  api       the axum surface: resolve, model/dataset info, tree, refs,
            whoami, metrics, bearer auth, range handling.
  bin       one binary: serve plus fetch/pin/refresh/list/show/rm/gc/
            verify/doctor.

Deployment targets bob.hanzalova.internal:20482 (port derived per
architecture/port-allocations.md §3), storing to the MinIO on
caveman.kosherinata.internal, fronted by hanzalova at rf.internal.
Ships the sysusers drop-in, hardened unit, firewalld service, nginx
vhost, config template, infra-setup.sh and the Gitea Actions
ci/deploy/conformance workflows.

Testing: 112 unit and integration tests, including the sovereignty
suite (cold fetch, sealed replay, single-flight, client disconnect,
range resume, freeze stability, gc-after-rm, digest mismatch), plus a
conformance suite driving a pinned huggingface_hub against a real Hub.

Deviations from the spec, all deliberate:
  - one binary with subcommands (spec §9) rather than generic.md's
    separate -api and -cli binaries; the library split is unchanged.
  - a dedicated sysusers account and hardened unit (generic.md §8)
    rather than the spec's illustrative DynamicUser unit.
  - manifests carry an optional repo_tree recorded verbatim, resolving
    spec §13's "record whole, filter on read" question for the tree
    endpoint as well as model-info.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XZG2i4AmfSqE97EJGBVb64
2026-08-31 10:46:25 +03:00