mirror of
https://github.com/KohakuBlueleaf/KohakuHub.git
synced 2026-07-10 19:57:19 -05:00
[PR #17] [MERGED] sync deepghs:dev/narugo1992 → main: 22 PRs across fallback / errors / cache / perf / UI (Apr–May 2026) #17
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/KohakuBlueleaf/KohakuHub/pull/17
Author: @narugo1992
Created: 5/5/2026
Status: ✅ Merged
Merged: 5/8/2026
Merged by: @KohakuBlueleaf
Base:
main← Head:dev/narugo1992📝 Commits (10+)
1397332feat(dev): unify make ui (admin under /admin) and stop spurious vite reloadsd039f12Merge pull request #34 from deepghs/feat/dev-server-quality-of-lifeb482171feat(admin): dependency health dashboard for Postgres / MinIO / LakeFS / SMTP9eeb5e7test(admin/health): cover failure paths so the patch matches project coverageb9a286ffix(admin/health): UI parity with sibling pages + real MinIO server versionad0f5bfMerge pull request #48 from deepghs/feat/admin-health-dashboard275266ffeat(admin): global credentials view (sessions / API tokens / SSH keys) with revokec53c080feat(seed): plant deterministic API tokens and SSH keys with usable keypairs2a4246bMerge pull request #49 from deepghs/feat/admin-credentials-viewf9bf4b0feat(ui): read-only browser for hfutils.index TAR + sidecar pairs📊 Changes
164 files changed (+42341 additions, -1453 deletions)
View changed files
📝
.env.dev.example(+6 -0)📝
.github/workflows/fullstack-tests.yml(+151 -6)➕
CHANGELOG.md(+74 -0)📝
CONTRIBUTING.md(+3 -5)📝
Makefile(+21 -9)📝
README.md(+24 -8)📝
codecov.yml(+27 -0)📝
config-example.toml(+1 -1)📝
docker-compose.example.yml(+40 -0)📝
docs/deployment.md(+15 -5)📝
docs/deployment/docker.md(+7 -5)📝
docs/deployment/production.md(+34 -0)➕
docs/development/cache.md(+174 -0)📝
docs/development/local-dev.md(+3 -4)📝
docs/setup.md(+13 -4)➕
package.json(+18 -0)➕
pnpm-workspace.yaml(+3 -0)📝
pyproject.toml(+1 -0)📝
scripts/README.md(+2 -1)📝
scripts/deploy.py(+10 -8)...and 80 more files
📄 Description
Summary
Up-streaming 94 commits / 22 PRs / 162 files (+41,351 / −1,450 lines) that landed on
deepghs/KohakuHub:dev/narugo1992between 2026-04-27 and 2026-05-05. The work clusters into four large feature threads (fallback chain repo-binding, HF error-contract alignment, an L2 cache infrastructure, and a list/info perf pass), plus a set of UI / admin / indexed-tar additions, a dev-server quality-of-life rework, and small bug fixes.This PR is the scheduled
dev/narugo1992→ upstream-mainship. Every URL below points at the corresponding deepghs PR / issue so cross-repo references survive verbatim.Source:
deepghs/KohakuHub:dev/narugo1992@f8773c4.Target:
KohakuBlueleaf/KohakuHub:main(parent fork).1 — Fallback chain: repo-grain binding (largest single thread)
deepghs/KohakuHub#77 — closes deepghs/KohakuHub#75
The fallback chain previously made per-operation, per-file decisions when picking a source. For one
repo_id, different reads in the same SPA session could land on different upstream sources —infofrom source A,treefrom source B,resolvefrom source C, all naming a "bert-base-uncased" but three different repos. This PR enforces arepo_id-scoped binding contract: once any operation confirms a repo lives on a given source, all subsequent reads against thatrepo_idgo to that source for the cache TTL window.The four
try_fallback_*loops now share a 3-state classifier (BIND_AND_RESPOND/BIND_AND_PROPAGATE/TRY_NEXT_SOURCE) whose priority mirrorshuggingface_hub.utils._http.hf_raise_for_status. The matrix is empirically anchored to live HF responses (re-probed multiple times during the branch's lifetime, most recently 2026-05-05).Several follow-up fixes/features landed on the same
feat/fallback-repo-bindingbranch before merge:(user, tokens_hash, repo_id)keying + three-dimensional generation counters (global / per-user / per-repo) + invalidation hooks on every mutation event (admin source mutations, user external-token rotations, local repo CRUD).asyncio.wait_forsupervisor so a stuckattempt_fncannot freeze same-repo callers indefinitely. Bundled with a Plan A redirect-passthrough on resolve GET so multi-GB blobs never traverse the backend.TypeError: 'NoneType' object does not support item assignmentregression caught in pre-merge testing.dict.pop(key, default)returnsNonewhen the key is present with aNonevalue (default doesn't apply); combined withclient_headers or Nonecollapsing empty dicts toNone, every token-bearing source 502'd on small-text-file resolves with"category":"network". Fixed at theFallbackClientcontract boundary.The strict-consistency contract is documented in
src/kohakuhub/api/fallback/README.md(rewritten as part of this thread) and deliberately narrowed in deepghs/KohakuHub#85 to "safety under stable config, scoped per-process, not a liveness gate."2 — HuggingFace error-contract alignment for permission denials
deepghs/KohakuHub#89 — closes deepghs/KohakuHub#76
check_repo_read_permissionpreviously raisedHTTPException(401)for anonymous-on-private andHTTPException(403)for authed-no-access — both produced FastAPI's default{"detail": "..."}envelope with noX-Error-Code. Ahuggingface_hubclient hitting a private hkub repo got a genericHfHubHTTPErrorinstead of the namedRepositoryNotFoundError, sotransformers/datasets/ etc. lost actionable error semantics.This PR introduces
RepoReadDeniedError(a non-HTTPExceptionexception class) raised bycheck_repo_read_permissionfor both anon-on-private and authed-no-access. A global FastAPI exception handler inmain.pyconverts it into404 + X-Error-Code: RepoNotFoundwith an empty body — matching what HF returns to authenticated callers.hf_raise_for_statusthen dispatchesRepositoryNotFoundErrorend-to-end (verified via live round-trip tests).Privacy-preserving Option A from the issue: anon and authed-no-access produce the same wire shape (no enumeration leak between "missing" and "private"); same client exception class; simpler than mirroring HF's anon-vs-authed split.
A
hf_disabled_repo()helper was also added — emits HF's exactX-Error-Message: "Access to this resource is disabled."string with noX-Error-Code(DisabledRepoError dispatch is keyed off the message verbatim). No call site yet; reserved for the future moderation feature. TheHFErrorCodedocstring labels its KohakuHub-only extensions distinctly from the four HF-recognized codes.Self-review during this PR caught one critical wrapper-interaction regression:
with_repo_fallbackhas a genericexcept Exceptioncatch (api/fallback/decorators.py:363) that absorbed the new exception and re-raised it as a 500. The original test suite missed it because the harness setsKOHAKU_HUB_FALLBACK_ENABLED=falseand every wire-shape test pre-emptively passes?fallback=false. Fixed by inserting an explicitexcept RepoReadDeniedError: raisebetween the cancellation handler and the generic catch, plus a dedicated regression test that forcescfg.fallback.enabled=True.3 — Cache & connection-pool infrastructure
KOHAKU_HUB_CACHE_URL. Includes a newsrc/kohakuhub/cache.pymodule with the cache primitive + boot-time flush coordinator (Mode-B namespaces wiped whenever Valkey'srun_idchanges since the last seen value, i.e. Valkey was restarted even if the API wasn't). Admin cache monitoring page + Redis probe added to/admin/api/health. 100% test coverage oncache.py, the admin cache router, and config validation.httpx.AsyncClientinLakeFSRestClientinstead of constructing one per request. Substantial p99 reduction on list/info paths that previously paid TLS handshake per LakeFS round-trip.4 — List / info / tree perf pass
LakeFS.get_branch + get_commitcalls in list endpoints (/api/models,/api/datasets,/api/spaces) with a single SQL aggregate (commit table).#72is thedev/narugo1992sync of#70. Coverage includes new upstream-compat tests againsthuggingface_hub.HfApi.list_models / list_datasets / list_spacesthat pin response shape across the matrix (0.20.x → latest)./org/{name}inlinesrepo_countdirectly from the DB instead of dispatching three frontendlistReposfan-outs (which themselves N+1'd into LakeFS).calculate_repository_storage. Quota calculations on large repos no longer scale O(files).lastCommitper page via LakeFS path-filteredlogCommitsinstead of walking commits client-side. Closes deepghs/KohakuHub#59 (tree-expand 30s timeout on WAN-deployed instances).5 — Indexed-tar feature suite
A coordinated three-PR thread for surfacing
hfutils.indexTAR-format datasets natively:hfutils.indexTAR + sidecar pairs (.tar+.jsonwith member offsets). Detects sibling-tar pairs server-side; backend exposes a TAR-member listing endpoint; SPA renders a tree-style member browser inside the regular file list..tarhas an indexed sibling, gating the indexed-tar UI.6 — Repo-list / tree UI features (HF-compatible)
name_prefixfilter on/tree(closes deepghs/KohakuHub#54). Matches HF's additive query parameter.7 — Admin tooling
8 — Dev-server / monorepo
make ui(admin SPA mounted under/admin); stop spurious Vite reloads triggered by Python file changes in shared dirs. Establishes the pnpm monorepo layout that subsequent PRs build on (src/kohaku-hub-ui+src/kohaku-hub-adminworkspaces).9 — Bug fixes
/resolve/Range probes from the SPA. Without it, private-repo Range reads from the parquet/safetensors preview path silently anonymized themselves and 401'd.headers=NoneTypeErrorregression caught in pre-merge testing of #77.Open follow-ups (intentionally not blocking this merge)
These were either explicitly scoped out of the PRs above, or surfaced post-merge during pre-
dev → mainreview. All tracked in the deepghs issue tracker; nothing here is new debt introduced by this PR thread without a corresponding tracker entry:kohakuhub.cachebackend so multi-worker deployments honour the strict-freshness contract across processes (rather than the current per-process scope).git/routers/http.pyis not wrapped bywith_repo_fallback, so the privacy translation hits git transport too —git cloneof a private repo now returns404 + empty bodyinstead of401 + WWW-Authenticate: Basic. Fix sketched in the issue.with_list_aggregationdefaultsfallback=true; every list call hits external sources. Pre-existing.except Exceptionantipatterns (168 sites). Pre-existing.Test posture
CI matrix on each landed PR covers backend tests across Python 3.10 / 3.11 / 3.12 ×
huggingface_hubversions {0.20.3, 0.30.2, 0.36.2, 1.0.1, 1.6.0, latest} (18 lanes), plus acache disabledlane, plus codecov + admin frontend + frontend unit tests. Every PR landed in this thread shipped CI-green. The most recent ones (#89, #88, #86) include hf_hub interop tests that drive a real client against a live test server.Significant new test artefacts:
test/kohakuhub/api/fallback/test_strict_consistency.py— invariants pinning the post-#77 binding contract.test/kohakuhub/api/fallback/test_strict_freshness.py— generation-counter race protection (#79).test/kohakuhub/api/fallback/test_chain_enumeration.py+test_e2e_matrix.py— exhaustive matrix covering every wire shape × every operation type ×hf_hub_download/model_info/list_repo_tree/get_paths_infodispatch behaviour.test/kohakuhub/api/test_repo_read_denial_hf_alignment.py— wire-shape + interop tests for #76 (#89) including the production-shape regression guard with fallback enabled.test/kohakuhub/test_cache.py— 100% coverage of the L2 cache primitive (#74).test/kohakuhub/test_lakefs_rest_client.py+test_lakefs_rest_client_live.py— pooling / lifecycle coverage for #61.Migration notes for operators
KOHAKU_HUB_FALLBACK_CACHE_TTL_SECONDSdefault lowered from300to30(#84). Existing deployments unaffected unless they explicitly relied on the longer window.KOHAKU_HUB_CACHE_URLis the new opt-in for the L2 cache (#74). Defaults to disabled; auto-enabled when set. Single-worker deployments without Redis continue to work as before.401 / 403 + JSONto404 + X-Error-Code: RepoNotFound + empty bodyfor the HF API surfaces (#89). The SPA already mapsRepoNotFoundand bare 401 toNOT_FOUND, so user-facing error UX shifts from "Forbidden" to "Not found" for outsiders on private repos — privacy-preserving by design.git clone(noWWW-Authenticate: Basicchallenge); see #90 for the planned fix.src/kohaku-hub-ui/+src/kohaku-hub-admin/are workspaces;make uiruns both. Anyone vendoring this fork's frontend should update build scripts to point atpnpmworkspaces (#34).Per-PR commit anchor table (ordered by merge time)
For full traceability:
d039f12make ui(admin under/admin) and stop spurious Vite reloadsad0f5bf2a4246bb98b482hfutils.indexTAR + sidecar pairs1e3d010c064357/resolve/Range probes174554ad68f2baname_prefixfilter on/treeb0d1279ad357eecalculate_repository_storageeb713424947f93httpx.AsyncClientinLakeFSRestClientca573eaa2ba6c3repo_count, drop frontendlistReposfan-outc8f375719938859e7254c44671334af6419asyncio.wait_forsupervisor (closes #85)a53acdde3089e6headers=Noneas emptyf8773c4🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
[PR #17] sync deepghs:dev/narugo1992 → main: 22 PRs across fallback / errors / cache / perf / UI (Apr–May 2026)to [PR #17] [MERGED] sync deepghs:dev/narugo1992 → main: 22 PRs across fallback / errors / cache / perf / UI (Apr–May 2026)