From c68840b520593044a79646dcd3af281fc03cfee5 Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Thu, 30 Jul 2026 00:56:49 +0800 Subject: [PATCH 1/2] chore(hfs): adopt v2.1 preview contract --- AGENTS.md | 4 ++-- README.md | 11 ++++++++--- docs/AGENTS.md | 6 +++--- docs/README.md | 2 +- docs/configuration.md | 4 ++-- docs/contract-alignment.md | 25 +++++++++++++++---------- docs/deployment-huggingface.md | 8 ++++---- docs/operations.md | 2 +- hfs-dev.candidate.toml | 6 +++++- hfs-dev.toml | 8 ++++++-- scripts/validate-contract.sh | 11 ++++++++++- 11 files changed, 57 insertions(+), 30 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index af59967..685fa8f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ | `Dockerfile` | Ubuntu builder/runtime、Go 下载、pinned upstream source build、runtime packages、healthcheck | No | 修改 base image、build args、`LIBREFS_COMMIT`、UID/GID、复制路径或 `HEALTHCHECK` 时 | | `hfs-dev.toml` | HFS development alignment manifest,声明 Pattern A、bundle-only build、Space root 和 release pin surface | No | 修改 HFS 分类、runtime 获取模式、required files、release hardening backlog 或 pin surface 时 | | `hfs/` | Runtime glue:container entrypoint、Nginx、ops/admin Python services | Yes | 修改启动流程、进程监管、路由、鉴权、control plane、复制路径或容器写入路径前 | -| `docs/` | 架构、配置、部署、运维、故障排查、契约对照和源码逐文件说明 | Yes | 修改任何文档、能力状态、endpoint、生产快照、HF Variables/Secrets/Volume 表述前 | +| `docs/` | 架构、配置、部署、运维、故障排查、契约对照和源码逐文件说明 | Yes | 修改任何文档、能力状态、endpoint、canonical preview 快照、HF Variables/Secrets/Volume 表述前 | | `scripts/` | 本地/远端契约验证和 credentialed S3 smoke 工具 | Yes | 修改 validation、smoke、SigV4、清理逻辑、远端验收或脚本参数前 | | `.dockerignore` | Docker build context 过滤,避免 `.env*`、`local/`、临时文件进入远端 build | No | 修改 build context 或本地材料忽略规则时 | | `.gitattributes` | Hugging Face/Git 展示和文件类型规则 | No | 修改 HF 文件类型、LFS 或展示规则时 | @@ -90,7 +90,7 @@ Mutating HF commands require explicit live-operation authorization: `hf spaces s - Hugging Face Space 外部只暴露 `7860`。`9000`、`9001`、`8081`、`8082` 都是容器内部端口,不要写成外部直连端口。 - S3 client 应使用 path-style addressing;HF Space 子域名下不要推荐 virtual-hosted bucket URL。 - 避免建议或创建名为 `console`、`minio`、`_ops`、`_admin` 的公开 bucket,因为这些路径与保留路由冲突。 -- 区分代码默认值和当前生产配置。`ADMIN_ENABLED` 代码默认必须是 `false`;当前线上状态必须用 HF Variables 或 `docs/contract-alignment.md` 的最新回读入口确认。 +- 区分代码默认值和当前 canonical preview 配置。`ADMIN_ENABLED` 代码默认必须是 `false`;当前线上状态必须用 HF Variables 或 `docs/contract-alignment.md` 的最新回读入口确认。 ## Runtime and control-plane invariants diff --git a/README.md b/README.md index cd6495f..832c15b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ LibreFS HFS 是一个面向 Hugging Face Docker Space 的 libreFS 部署包装 - Docker build 阶段安装 Go,并从 `https://github.com/libreFS/libreFS.git` 拉取源码编译。 - Runtime 阶段仍然使用 `ubuntu:24.04`。 - 不使用 libreFS 官方 Docker image。 -- 仓库根目录同时作为 Hugging Face Space root 和 GitHub 维护 root;`hfs-dev.toml` 声明 HFS v2 Pattern A / `port` / `source` 关系:生产版本始终由 `LIBREFS_COMMIT` 的上游 commit 固定,多服务 runtime glue 集中在 `hfs/`。 +- 仓库根目录同时作为 Hugging Face Space root 和 GitHub 维护 root;`hfs-dev.toml` 声明 HFS v2.1 `preview` / `primary` / Pattern A / `port` / `source` 关系:可复现 wrapper 始终由 `LIBREFS_COMMIT` 的上游 commit 固定,多服务 runtime glue 集中在 `hfs/`。 - 标准交付只上传由 `scripts/export-space-bundle.sh` 从干净、不可变 Git commit 导出的最小 wrapper;bundle 自带 `BUILD_SOURCE.json` 和 `SHA256SUMS`,同时绑定 wrapper SHA 与实际 libreFS source SHA,不含 libreFS 产品源码、`.env*`、`local/`、缓存、生成数据或凭证。 - 使用 Nginx 把 libreFS 的 S3 API 和 Web Console 合并到 Hugging Face Space 对外暴露的单端口 `7860`。 @@ -84,7 +84,12 @@ Hugging Face Docker Space 只对外暴露一个 app port。本项目用 Nginx | Variable | `ADMIN_ENABLED` | `false` | 是否开启 `/_admin/`;默认保持关闭。 | | Variable | `CONTROL_PLANE_DEFAULT_LANG` | `en` | `/_ops/` 和 `/_admin/` JSON 文案默认语言;支持 `en`、`zh-CN`。 | -## 当前生产配置快照 +## 当前 canonical preview 配置快照 + +日常 Preview 变更允许直接更新 canonical Space;`hfs-dev.candidate.toml` 只用于高风险变更 +的可选隔离验证,不是常规前置门禁。canonical Secret 必须先存在于 manifest 声明的本地 +明文 `.env`;candidate 使用独立的 `local/hfs-targets/candidate.env`。这些文件保持 Git +ignored,HF Secret 只能作为部署副本。 最近回读时间:2026-06-03。实时状态以命令重新查询为准。 @@ -187,7 +192,7 @@ https://blueskyxn-librefs-hfs.hf.space// ## 已知边界 - 当前 `hf spaces volumes list` 显示 `/data` 已挂载 Hugging Face Storage Bucket;如果后续移除挂载,上传对象可能在 Space 重启、重建、迁移或停止后丢失。 -- 当前生产环境已显式开启 `/_admin/`。如果需要恢复默认安全姿态,应把 HF Variable `ADMIN_ENABLED` 改回 `false` 或移除。 +- 当前 canonical preview Space 已显式开启 `/_admin/`。如果需要恢复默认安全姿态,应把 HF Variable `ADMIN_ENABLED` 改回 `false` 或移除。 - 当前 `cpu-basic` 硬件适合功能测试和轻量使用,不适合高吞吐对象存储。 - 未签名浏览器直接访问根路径 `/` 可能返回 S3 XML error,这是正常现象;签名 S3 请求和配置了 policy 的对象直链才是预期访问方式。 - 本仓库 license 使用 AGPL-3.0,因为 libreFS 本身是 AGPL-3.0。 diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 12e2eee..4d7ce2b 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -2,11 +2,11 @@ `docs/` is the public documentation and operational fact source for LibreFS HFS. Read this card before editing live state, endpoints, Secret/Variable names, ops/admin, or persistence wording. -Start with `docs/contract-alignment.md` for runtime behavior or production snapshots. +Start with `docs/contract-alignment.md` for runtime behavior or canonical preview snapshots. ## Local invariants -- Separate code defaults from production config; read back live state before calling it current. +- Separate code defaults from canonical preview config; read back live state before calling it current. - Document Secret keys and presence only; never write token, password, access-key, or private URL values. - Health checks prove route/process availability only, not S3 writes, policy, public reads, or persistence. - `/data` Volume attached is not persistence validation; require upload, restart, read, rebuild, and read again. @@ -15,7 +15,7 @@ Start with `docs/contract-alignment.md` for runtime behavior or production snaps ## Update order -- Runtime contract or production snapshot: update `docs/contract-alignment.md` first, then README and affected docs. +- Runtime contract or canonical preview snapshot: update `docs/contract-alignment.md` first, then README and affected docs. - Endpoint, Console URL, S3 URL, ops/admin route, login, or token transport: check README plus `configuration.md`, `operations.md`, `architecture.md`, and `source-walkthrough.md`. - `troubleshooting.md` should cover real or high-probability failures with evidence, not speculative catalogs. diff --git a/docs/README.md b/docs/README.md index fdbb5f0..da746ab 100644 --- a/docs/README.md +++ b/docs/README.md @@ -44,7 +44,7 @@ https://blueskyxn-librefs-hfs.hf.space/console/ ## 本地轻量验证 -不安装项目依赖、不本地编译 libreFS 时,可以先运行仓库契约检查。它同时检查 HFS v2 source-lane manifest、local ledger ignore 边界、allowlisted source bundle fixture、provenance 和 manual deployment workflow: +不安装项目依赖、不本地编译 libreFS 时,可以先运行仓库契约检查。它同时检查 HFS v2.1 source-lane manifest、local ledger ignore 边界、allowlisted source bundle fixture、provenance 和 manual deployment workflow: ```bash scripts/validate-contract.sh diff --git a/docs/configuration.md b/docs/configuration.md index ae6f6ee..8f5b9f2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -50,7 +50,7 @@ fatal: couldn't find remote ref main ## Hugging Face Variables -原则:不要把和代码默认值、upstream 默认值相同的配置同步到 Hugging Face Variables。Variables 只用于表达“这个 Space 明确要覆盖默认行为”。代码默认部署下,HF Variables 可以为空;当前生产环境为了开启 admin,已显式设置 `ADMIN_ENABLED=true`,并显式设置 `ADMIN_AUDIT_LOG=/tmp/librefs-hfs/admin-audit.jsonl` 让 admin audit 不写入 `/data`。 +原则:不要把和代码默认值、upstream 默认值相同的配置同步到 Hugging Face Variables。Variables 只用于表达“这个 Space 明确要覆盖默认行为”。代码默认部署下,HF Variables 可以为空;当前 canonical preview Space 为了开启 admin,已显式设置 `ADMIN_ENABLED=true`,并显式设置 `ADMIN_AUDIT_LOG=/tmp/librefs-hfs/admin-audit.jsonl` 让 admin audit 不写入 `/data`。 | Variable | 必需 | 默认值 | 什么时候设置 | | --- | --- | --- | --- | @@ -90,7 +90,7 @@ HF Volume: - BlueSkyXN/librefs-hfs-data -> /data ``` -当前生产环境最近回读状态(2026-06-03): +当前 canonical preview Space 最近回读状态(2026-06-03): ```text HF Secrets: diff --git a/docs/contract-alignment.md b/docs/contract-alignment.md index eabebb3..1e1d9e1 100644 --- a/docs/contract-alignment.md +++ b/docs/contract-alignment.md @@ -1,10 +1,10 @@ # 代码-文档契约对照 -本文档把当前代码事实、生产回读状态和文档维护口径放在同一处,用于减少文档漂移。修改代码或远端配置后,先更新这里,再同步其他文档。 +本文档把当前代码事实、canonical preview 回读状态和文档维护口径放在同一处,用于减少文档漂移。修改代码或远端配置后,先更新这里,再同步其他文档。 最后核对时间:2026-06-03。 -## 当前生产回读 +## 当前 canonical preview 回读 | 项目 | 当前状态 | 证据命令 | | --- | --- | --- | @@ -15,26 +15,31 @@ | HF Secrets | `MINIO_ROOT_USER`、`MINIO_ROOT_PASSWORD`、`OPS_TOKEN`、`ADMIN_TOKEN` 已存在;HF 不回显 value。 | `hf spaces secrets list BlueSkyXN/libreFS-HFS` | | HF Volume | `bucket BlueSkyXN/librefs-hfs-data -> /data`,`read_only=False` | `hf spaces volumes list BlueSkyXN/libreFS-HFS` | -生产状态是快照,不是永久保证。涉及实时状态、Secret 同步、Volume 挂载或 runtime sha 时必须重新回读。 +canonical preview 状态是快照,不是永久保证。涉及实时状态、Secret 同步、Volume 挂载或 runtime sha 时必须重新回读。 + +本项目按 HFS v2.1 登记为 `project_class=preview`,canonical Space 的角色是 `primary`。 +日常 Preview 变更允许直接更新 canonical Space;candidate 只作为高风险变更的可选隔离验证, +不是常规前置门禁。Secret 必须先写入 manifest 声明的 Git ignored 本地明文文件;HF Secret +只能作为部署副本,不能成为唯一事实源。 ## 不可漂移契约 | 契约点 | 当前事实 | 权威来源 | 文档同步位置 | | --- | --- | --- | --- | | Space 类型 | Docker Space,`app_port: 7860`,`license: agpl-3.0` | `README.md` front matter | `README.md`, `docs/configuration.md`, `docs/deployment-huggingface.md` | -| HFS 范式分类 | HFS v2 Pattern A / `port` / `source`;`version_source=commit`,repo root 同时是 Space root 和 GitHub 维护 root,runtime glue 收在 `hfs/` | `hfs-dev.toml`, `README.md`, `Dockerfile`, `hfs/` | `README.md`, `docs/architecture.md`, `docs/source-walkthrough.md`, `AGENTS.md` | +| HFS 范式分类 | HFS v2.1 / `preview` / `primary` / Pattern A / `port` / `source`;`version_source=commit`,repo root 同时是 Space root 和 GitHub 维护 root,runtime glue 收在 `hfs/` | `hfs-dev.toml`, `README.md`, `Dockerfile`, `hfs/` | `README.md`, `docs/architecture.md`, `docs/source-walkthrough.md`, `AGENTS.md` | | Runtime 获取模式 | `bundle-only-build`;Docker build 只能从 clean wrapper bundle 读取 provenance,并从 libreFS upstream `git fetch` 其记录的 source commit 后编译 | `hfs-dev.toml`, `Dockerfile` | `README.md`, `docs/architecture.md`, `docs/development-plan.md` | | Source wrapper provenance | 受控发布只上传由 clean immutable wrapper commit 导出的 allowlisted bundle;`BUILD_SOURCE.json` 和 `SHA256SUMS` 被 Docker image 保存,startup 校验 wrapper SHA、libreFS source SHA、digest 和 schema,`/_ops/version` 只返回无密 provenance 摘要 | `scripts/export-space-bundle.sh`, `scripts/verify-space-bundle.sh`, `Dockerfile`, `hfs/start.sh`, `hfs/ops_service.py` | `README.md`, `docs/deployment-huggingface.md`, `docs/operations.md`, `docs/source-walkthrough.md` | | 外部端口 | 只暴露 `7860` | `Dockerfile` `EXPOSE 7860`,`hfs/nginx.conf` `listen 7860` | 全部 endpoint/port 文档 | | 构建策略 | Ubuntu builder/runtime,从 `https://github.com/libreFS/libreFS.git` 拉源码编译,不使用官方 image | `Dockerfile` | `README.md`, `docs/architecture.md`, `docs/source-walkthrough.md` | | Go 版本 | `GO_VERSION=1.26.3` | `Dockerfile` | `docs/configuration.md`, `docs/source-walkthrough.md`, `docs/deployment-huggingface.md` | | libreFS ref | bundle-only build 必须同时使用 `HFS_RELEASE_BUILD=true`、`LIBREFS_COMMIT=` 与 bundle 内相同的 `librefs_source_commit`;Docker build 会直接 fetch/checkout 并校验 `git rev-parse HEAD` | `Dockerfile`, `hfs-dev.toml` | `docs/configuration.md`, `docs/troubleshooting.md`, `docs/development-plan.md` | -| Release hardening | HFS v2 registry不复制 product pin;受控 build 通过 `HFS_RELEASE_BUILD=true` + `LIBREFS_COMMIT=<40 位 SHA>` 固定 upstream。Go tarball checksum 和 Ubuntu base image digest仍是后续 hardening,不改当前 runtime | `Dockerfile`, `hfs-dev.toml` | `docs/configuration.md`, `docs/development-plan.md` | +| Release hardening | HFS v2.1 registry不复制 product pin;受控 build 通过 `HFS_RELEASE_BUILD=true` + `LIBREFS_COMMIT=<40 位 SHA>` 固定 upstream。Go tarball checksum 和 Ubuntu base image digest仍是后续 hardening,不改当前 runtime | `Dockerfile`, `hfs-dev.toml` | `docs/configuration.md`, `docs/development-plan.md` | | Runtime packages | `bash`、`ca-certificates`、`curl`、`nginx`、`python3`、`tini` | `Dockerfile` | `docs/architecture.md`, `docs/source-walkthrough.md` | | Runtime user | UID/GID `1000`,存在则复用,不无条件创建 | `Dockerfile` | `docs/source-walkthrough.md`, `docs/troubleshooting.md` | | 必需启动 Secrets | 只有 `MINIO_ROOT_USER` 和 `MINIO_ROOT_PASSWORD` 缺失会让 `hfs/start.sh` 立即退出 | `hfs/start.sh` | `docs/configuration.md`, `docs/deployment-huggingface.md`, `docs/troubleshooting.md` | -| Ops token | `OPS_TOKEN` 默认 `librefs_ops_demo_token`,生产应使用 HF Secret 覆盖 | `hfs/start.sh`, `hfs/ops_service.py` | `README.md`, `docs/configuration.md`, `docs/operations.md` | -| Admin 开关 | 代码默认 `ADMIN_ENABLED=false`;当前生产回读为 `ADMIN_ENABLED=true` | `hfs/start.sh`, HF Variables | `README.md`, `docs/configuration.md`, `docs/operations.md`, `docs/troubleshooting.md` | +| Ops token | `OPS_TOKEN` 默认 `librefs_ops_demo_token`;共享或长期运行的 preview 应使用本地明文先行的 HF Secret 覆盖 | `hfs/start.sh`, `hfs/ops_service.py` | `README.md`, `docs/configuration.md`, `docs/operations.md` | +| Admin 开关 | 代码默认 `ADMIN_ENABLED=false`;当前 canonical preview 回读为 `ADMIN_ENABLED=true` | `hfs/start.sh`, HF Variables | `README.md`, `docs/configuration.md`, `docs/operations.md`, `docs/troubleshooting.md` | | Admin token | 开启 admin 时必须设置 `ADMIN_TOKEN`;使用 `X-Admin-Token` 或 bearer token;代码不强制它与 `OPS_TOKEN` 不同 | `hfs/admin_service.py` | `docs/configuration.md`, `docs/operations.md`, `docs/architecture.md` | | 公开 URL 推导 | `PUBLIC_BASE_URL` > `SPACE_HOST` > `http://localhost:7860` | `hfs/start.sh` | `docs/architecture.md`, `docs/configuration.md`, `docs/source-walkthrough.md` | | `MINIO_SERVER_URL` | 必须有 `http://` 或 `https://`,并去掉尾部 `/` | `hfs/start.sh` | `docs/architecture.md`, `docs/configuration.md`, `docs/source-walkthrough.md` | @@ -49,16 +54,16 @@ | Admin 写操作 | `reload-nginx` 是写 action,必须 JSON body `{"confirm": true}`,并写审计日志 | `hfs/admin_service.py` | `docs/architecture.md`, `docs/configuration.md`, `docs/operations.md` | | Admin 非目标 | 没有 Web terminal、file manager、bucket/policy/root credential 管理或 `librefs` restart | `hfs/admin_service.py`, 当前路由 | `README.md`, `docs/architecture.md`, `docs/configuration.md`, `docs/usage.md`, `docs/operations.md` | | 双语文案 | 支持 `en` 和 `zh-CN`;语言优先级为 `?lang=`、`X-Control-Language`、`Accept-Language`、`CONTROL_PLANE_DEFAULT_LANG`、默认 `en` | `hfs/ops_service.py`, `hfs/admin_service.py` | `README.md`, `docs/configuration.md`, `docs/operations.md`, `docs/architecture.md` | -| 数据目录 | libreFS 数据默认在 `/data`;admin audit log 默认在 `/tmp/librefs-hfs/admin-audit.jsonl`;当前生产挂载 Storage Bucket 到 `/data` | `hfs/start.sh`, `hfs/admin_service.py`, HF Volumes | `README.md`, `docs/architecture.md`, `docs/operations.md`, `docs/usage.md` | +| 数据目录 | libreFS 数据默认在 `/data`;admin audit log 默认在 `/tmp/librefs-hfs/admin-audit.jsonl`;当前 canonical preview 挂载 Storage Bucket 到 `/data` | `hfs/start.sh`, `hfs/admin_service.py`, HF Volumes | `README.md`, `docs/architecture.md`, `docs/operations.md`, `docs/usage.md` | | 持久化口径 | Volume 挂载不等于持久化验收通过;仍需上传、重启、读取、rebuild、再读取 | 运维要求 | 所有持久化说明 | | S3 smoke | `scripts/smoke-s3-curl.sh` 会真实创建临时 bucket/object、设置 public read policy 并清理 | `scripts/smoke-s3-curl.sh` | `docs/README.md`, `docs/operations.md`, `docs/source-walkthrough.md` | | 契约验证 | `scripts/validate-contract.sh` 检查 front matter、Dockerfile、`hfs/start.sh`、Python、Nginx、license 和可选远端 health | `scripts/validate-contract.sh` | `docs/README.md`, `docs/operations.md`, `docs/source-walkthrough.md` | ## 文档维护规则 -1. 区分“代码默认值”和“当前生产配置”。例如 `ADMIN_ENABLED` 代码默认是 `false`,但当前生产是 `true`。 +1. 区分“代码默认值”和“当前 canonical preview 配置”。例如 `ADMIN_ENABLED` 代码默认是 `false`,但当前 preview 快照是 `true`。 2. 不把 Secret 明文写入文档。HF CLI 只能证明 key 存在;value 同步必须用受保护本机 `.env` 的值调线上接口验证。 3. 不把 health check 写成 S3 功能验收。S3 写入、下载、policy 和匿名直链必须用凭证型 smoke test 验证。 4. 不把 Volume 挂载写成持久化已验收。必须完成重启和 rebuild 后读回。 5. 修改 `hfs/ops_service.py` 或 `hfs/admin_service.py` 时,同步检查 `docs/configuration.md`、`docs/operations.md`、`docs/architecture.md` 和本文档。 -6. 修改远端 HF Variables、Secrets 或 Volume 后,同步更新“当前生产回读”,并保留“代码默认值”不变。 +6. 修改远端 HF Variables、Secrets 或 Volume 后,同步更新“当前 canonical preview 回读”,并保留“代码默认值”不变。 diff --git a/docs/deployment-huggingface.md b/docs/deployment-huggingface.md index d323fca..262f35d 100644 --- a/docs/deployment-huggingface.md +++ b/docs/deployment-huggingface.md @@ -37,7 +37,7 @@ hf spaces secrets add BlueSkyXN/libreFS-HFS \ -s OPS_TOKEN='' ``` -如果当前生产策略需要开启 `/_admin/`,还需要设置: +如果当前 canonical preview 策略需要开启 `/_admin/`,还需要设置: ```bash hf spaces secrets add BlueSkyXN/libreFS-HFS \ @@ -56,7 +56,7 @@ hf spaces secrets list BlueSkyXN/libreFS-HFS ## 可选 Variables -代码默认部署不需要配置 HF Variables。不要把和代码默认值或 upstream 默认值相同的变量同步到 Hugging Face;这会让云端配置看起来像有很多“特殊设置”,实际只是噪音。当前生产环境为了开启 admin,已显式设置 `ADMIN_ENABLED=true`。 +代码默认部署不需要配置 HF Variables。不要把和代码默认值或 upstream 默认值相同的变量同步到 Hugging Face;这会让云端配置看起来像有很多“特殊设置”,实际只是噪音。当前 canonical preview Space 为了开启 admin,已显式设置 `ADMIN_ENABLED=true`。 | Variable | 默认值 | 什么时候设置 | | --- | --- | --- | @@ -89,7 +89,7 @@ hf spaces variables list BlueSkyXN/libreFS-HFS No results found. ``` -当前生产环境最近回读为 2026-06-03 快照: +当前 canonical preview Space 最近回读为 2026-06-03 快照: ```text ADMIN_ENABLED=true @@ -230,7 +230,7 @@ WebUI: https://blueskyxn-librefs-hfs.hf.space/console/ 3. 配置 `MINIO_ROOT_USER`。 4. 配置 `MINIO_ROOT_PASSWORD`。 5. 配置 `OPS_TOKEN`。 -6. 如果需要生产环境开启 admin,配置 `ADMIN_TOKEN` 和 `ADMIN_ENABLED=true`。 +6. 如果需要 canonical preview Space 开启 admin,先在本地明文来源配置 `ADMIN_TOKEN`,再同步 Secret,并设置 `ADMIN_ENABLED=true`。 7. 推送仓库文件。 8. 等待 Space stage 变为 `RUNNING`。 9. 检查 `/minio/health/ready`。 diff --git a/docs/operations.md b/docs/operations.md index 3e50c4d..603234a 100644 --- a/docs/operations.md +++ b/docs/operations.md @@ -72,7 +72,7 @@ scripts/validate-contract.sh --remote `--remote` 会访问线上 endpoint,因此不属于离线门禁。source wrapper Docker build 同样会从 GitHub 获取 libreFS 上游源码;本地只记录为 skipped,不能把静态检查当作 build 成功。 -## HFS v2 source 交付证据 +## HFS v2.1 source 交付证据 一次受控发布至少要分别保留以下无密证据,且不要把任意一项替代另一项: diff --git a/hfs-dev.candidate.toml b/hfs-dev.candidate.toml index a00c0f0..1b2d33f 100644 --- a/hfs-dev.candidate.toml +++ b/hfs-dev.candidate.toml @@ -1,9 +1,13 @@ -standard = "2.0" +standard = "2.1" project = "librefs-hfs" space = "BlueSkyXN/libreFS-HFS-v2-candidate" +project_class = "preview" +target_role = "candidate" sovereignty = "port" lane = "source" version_source = "commit" +env_file = "local/hfs-targets/candidate.env" +secret_files = [] pattern = "A" runtime_mode = "bundle-only-build" diff --git a/hfs-dev.toml b/hfs-dev.toml index bf04181..d8782e9 100644 --- a/hfs-dev.toml +++ b/hfs-dev.toml @@ -1,13 +1,17 @@ -standard = "2.0" +standard = "2.1" project = "librefs-hfs" space = "BlueSkyXN/libreFS-HFS" +project_class = "preview" +target_role = "primary" sovereignty = "port" lane = "source" version_source = "commit" +env_file = ".env" +secret_files = [] # This is a semantic registry only. Dockerfile and hfs/start.sh remain the # authoritative locations for the upstream pin validation and runtime rules. -# Every production build is exported as a minimal wrapper bundle and compiles +# Every reviewed wrapper build is exported as a minimal bundle and compiles # the one immutable libreFS commit recorded in that bundle's provenance. pattern = "A" runtime_mode = "bundle-only-build" diff --git a/scripts/validate-contract.sh b/scripts/validate-contract.sh index c01fac8..a1a36b2 100755 --- a/scripts/validate-contract.sh +++ b/scripts/validate-contract.sh @@ -87,10 +87,19 @@ require_pattern README.md '^license: agpl-3.0$' 'README.md must keep license: ag check "HFS v2 semantic registry" test -f hfs-dev.toml test -f hfs-dev.candidate.toml -require_pattern hfs-dev.toml '^standard = "2\.0"$' 'manifest must use HFS standard 2.0' +require_pattern hfs-dev.toml '^standard = "2\.1"$' 'manifest must use HFS standard 2.1' +require_pattern hfs-dev.candidate.toml '^standard = "2\.1"$' 'candidate manifest must use HFS standard 2.1' require_pattern hfs-dev.toml '^project = "librefs-hfs"$' 'manifest must declare the wrapper project' require_pattern hfs-dev.toml '^space = "BlueSkyXN/libreFS-HFS"$' 'manifest must declare the target Space' require_pattern hfs-dev.candidate.toml '^space = "BlueSkyXN/libreFS-HFS-v2-candidate"$' 'candidate manifest must declare the private candidate Space' +require_pattern hfs-dev.toml '^project_class = "preview"$' 'canonical manifest must classify the project as preview' +require_pattern hfs-dev.toml '^target_role = "primary"$' 'canonical manifest must declare the primary target role' +require_pattern hfs-dev.toml '^env_file = "\.env"$' 'canonical manifest must declare the local plaintext ledger' +require_pattern hfs-dev.toml '^secret_files = \[\]$' 'canonical manifest must declare no structured secret files' +require_pattern hfs-dev.candidate.toml '^project_class = "preview"$' 'candidate manifest must classify the project as preview' +require_pattern hfs-dev.candidate.toml '^target_role = "candidate"$' 'candidate manifest must declare the candidate target role' +require_pattern hfs-dev.candidate.toml '^env_file = "local/hfs-targets/candidate\.env"$' 'candidate manifest must use an isolated local plaintext ledger' +require_pattern hfs-dev.candidate.toml '^secret_files = \[\]$' 'candidate manifest must declare no structured secret files' require_pattern hfs-dev.toml '^sovereignty = "port"$' 'libreFS-HFS must remain a port wrapper' require_pattern hfs-dev.toml '^lane = "source"$' 'libreFS-HFS must remain in the source lane' require_pattern hfs-dev.toml '^version_source = "commit"$' 'manifest must declare commit-based production provenance' From 59dd331af26552f101fe65d1cb653e9e313b9079 Mon Sep 17 00:00:00 2001 From: BlueSkyXN <63384277+BlueSkyXN@users.noreply.github.com> Date: Fri, 31 Jul 2026 01:05:04 +0800 Subject: [PATCH 2/2] fix(hfs): enforce protected visibility contract --- .github/workflows/deploy-hf-space.yml | 6 ++++-- docs/source-walkthrough.md | 2 +- hfs-dev.candidate.toml | 2 ++ hfs-dev.toml | 2 ++ scripts/sample-hf-bucket-storage.sh | 4 ++-- scripts/validate-contract.sh | 13 +++++++++---- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy-hf-space.yml b/.github/workflows/deploy-hf-space.yml index 113bdd5..877af62 100644 --- a/.github/workflows/deploy-hf-space.yml +++ b/.github/workflows/deploy-hf-space.yml @@ -27,8 +27,8 @@ concurrency: env: FORMAL_SPACE: BlueSkyXN/libreFS-HFS - HF_CLI_VERSION: "1.5.0" - HF_CLI_CLICK_VERSION: "8.3.3" + HF_CLI_VERSION: "1.25.1" + HF_CLI_CLICK_VERSION: "8.4.2" jobs: deploy: @@ -55,6 +55,8 @@ jobs: python3 -m pip install --disable-pip-version-check \ "huggingface_hub==${HF_CLI_VERSION}" \ "click==${HF_CLI_CLICK_VERSION}" + python3 -m huggingface_hub.cli.hf version + python3 -m huggingface_hub.cli.hf repos settings --help | grep -- --protected export SPACE_ID LIBREFS_COMMIT HFS_TARGET="${{ inputs.target }}" python3 - <<'PY' import os diff --git a/docs/source-walkthrough.md b/docs/source-walkthrough.md index 9dc539f..cf6b67c 100644 --- a/docs/source-walkthrough.md +++ b/docs/source-walkthrough.md @@ -465,7 +465,7 @@ scripts/sample-hf-bucket-storage.sh \ --ops-url https://blueskyxn-librefs-hfs.hf.space/_ops ``` -脚本固定验证 `huggingface_hub==1.5.0` 与 `click==8.3.3`,然后调用: +脚本固定验证 `huggingface_hub==1.25.1` 与 `click==8.4.2`,然后调用: - `HfApi().bucket_info("$bucket")`,生成只包含 bucket metadata 的结构化 JSON - `python3 -m huggingface_hub.cli.hf buckets list "$bucket" --recursive --format json` diff --git a/hfs-dev.candidate.toml b/hfs-dev.candidate.toml index 1b2d33f..27967fe 100644 --- a/hfs-dev.candidate.toml +++ b/hfs-dev.candidate.toml @@ -3,6 +3,8 @@ project = "librefs-hfs" space = "BlueSkyXN/libreFS-HFS-v2-candidate" project_class = "preview" target_role = "candidate" +space_visibility = "protected" +bucket_visibility = "private" sovereignty = "port" lane = "source" version_source = "commit" diff --git a/hfs-dev.toml b/hfs-dev.toml index ee67fb9..8cc3c57 100644 --- a/hfs-dev.toml +++ b/hfs-dev.toml @@ -3,6 +3,8 @@ project = "librefs-hfs" space = "BlueSkyXN/libreFS-HFS" project_class = "preview" target_role = "primary" +space_visibility = "protected" +bucket_visibility = "private" sovereignty = "port" lane = "source" version_source = "commit" diff --git a/scripts/sample-hf-bucket-storage.sh b/scripts/sample-hf-bucket-storage.sh index 8c16ca6..a45b21d 100755 --- a/scripts/sample-hf-bucket-storage.sh +++ b/scripts/sample-hf-bucket-storage.sh @@ -2,8 +2,8 @@ set -Eeuo pipefail DEFAULT_BUCKET="BlueSkyXN/librefs-hfs-data" -EXPECTED_HF_HUB_VERSION="1.5.0" -EXPECTED_CLICK_VERSION="8.3.3" +EXPECTED_HF_HUB_VERSION="1.25.1" +EXPECTED_CLICK_VERSION="8.4.2" BUCKET="${HF_BUCKET_ID:-$DEFAULT_BUCKET}" OPS_URL="${OPS_URL:-}" INTERVAL=0 diff --git a/scripts/validate-contract.sh b/scripts/validate-contract.sh index d98b806..846d2c4 100755 --- a/scripts/validate-contract.sh +++ b/scripts/validate-contract.sh @@ -94,10 +94,14 @@ require_pattern hfs-dev.toml '^space = "BlueSkyXN/libreFS-HFS"$' 'manifest must require_pattern hfs-dev.candidate.toml '^space = "BlueSkyXN/libreFS-HFS-v2-candidate"$' 'candidate manifest must declare the private candidate Space' require_pattern hfs-dev.toml '^project_class = "preview"$' 'canonical manifest must classify the project as preview' require_pattern hfs-dev.toml '^target_role = "primary"$' 'canonical manifest must declare the primary target role' +require_pattern hfs-dev.toml '^space_visibility = "protected"$' 'canonical Space visibility must be Protected' +require_pattern hfs-dev.toml '^bucket_visibility = "private"$' 'canonical bucket visibility must be Private' require_pattern hfs-dev.toml '^env_file = "\.env"$' 'canonical manifest must declare the local plaintext ledger' require_pattern hfs-dev.toml '^secret_files = \[\]$' 'canonical manifest must declare no structured secret files' require_pattern hfs-dev.candidate.toml '^project_class = "preview"$' 'candidate manifest must classify the project as preview' require_pattern hfs-dev.candidate.toml '^target_role = "candidate"$' 'candidate manifest must declare the candidate target role' +require_pattern hfs-dev.candidate.toml '^space_visibility = "protected"$' 'candidate Space visibility must be Protected' +require_pattern hfs-dev.candidate.toml '^bucket_visibility = "private"$' 'candidate bucket visibility must be Private' require_pattern hfs-dev.candidate.toml '^env_file = "local/hfs-targets/candidate\.env"$' 'candidate manifest must use an isolated local plaintext ledger' require_pattern hfs-dev.candidate.toml '^secret_files = \[\]$' 'candidate manifest must declare no structured secret files' require_pattern hfs-dev.toml '^sovereignty = "port"$' 'libreFS-HFS must remain a port wrapper' @@ -215,8 +219,8 @@ require_pattern scripts/smoke-s3-curl.sh 'Authorization: Bearer' 'private candid require_pattern scripts/smoke-s3-curl.sh 'Refusing to use bucket' 'S3 smoke test must refuse existing buckets' check "storage sampler script contract" test -f scripts/sample-hf-bucket-storage.sh -require_pattern scripts/sample-hf-bucket-storage.sh '^EXPECTED_HF_HUB_VERSION="1\.5\.0"$' 'storage sampler must pin huggingface_hub 1.5.0' -require_pattern scripts/sample-hf-bucket-storage.sh '^EXPECTED_CLICK_VERSION="8\.3\.3"$' 'storage sampler must pin the module CLI click runtime' +require_pattern scripts/sample-hf-bucket-storage.sh '^EXPECTED_HF_HUB_VERSION="1\.25\.1"$' 'storage sampler must pin huggingface_hub 1.25.1' +require_pattern scripts/sample-hf-bucket-storage.sh '^EXPECTED_CLICK_VERSION="8\.4\.2"$' 'storage sampler must pin click 8.4.2' require_pattern scripts/sample-hf-bucket-storage.sh 'HfApi\(\)\.bucket_info\(sys\.argv\[1\]\)' 'storage sampler must use structured HfApi bucket accounting' require_pattern scripts/sample-hf-bucket-storage.sh 'python3 -m huggingface_hub\.cli\.hf buckets list' 'storage sampler must use the pinned module CLI for the visible tree' require_pattern scripts/sample-hf-bucket-storage.sh '"\$BUCKET" --recursive --format json' 'storage sampler must request recursive JSON visible-tree output' @@ -267,10 +271,11 @@ require_pattern .github/workflows/deploy-hf-space.yml 'scripts/verify-space-bund require_pattern .github/workflows/deploy-hf-space.yml 'Refuse a Space repository outside the wrapper boundary' 'workflow must fail closed on legacy Space files' require_pattern .github/workflows/deploy-hf-space.yml 'huggingface_hub\.cli\.hf download' 'workflow must read back the Space repository through the pinned module CLI' require_pattern .github/workflows/deploy-hf-space.yml 'huggingface_hub\.cli\.hf upload' 'workflow must upload the Space repository through the pinned module CLI' -require_pattern .github/workflows/deploy-hf-space.yml 'HF_CLI_VERSION: "1\.5\.0"' 'workflow must pin huggingface_hub 1.5.0' -require_pattern .github/workflows/deploy-hf-space.yml 'HF_CLI_CLICK_VERSION: "8\.3\.3"' 'workflow must pin the module CLI click runtime' +require_pattern .github/workflows/deploy-hf-space.yml 'HF_CLI_VERSION: "1\.25\.1"' 'workflow must pin Protected-compatible huggingface_hub 1.25.1' +require_pattern .github/workflows/deploy-hf-space.yml 'HF_CLI_CLICK_VERSION: "8\.4\.2"' 'workflow must pin the module CLI click runtime' require_pattern .github/workflows/deploy-hf-space.yml 'huggingface_hub==\$\{HF_CLI_VERSION\}' 'workflow must install the pinned huggingface_hub version' require_pattern .github/workflows/deploy-hf-space.yml 'click==\$\{HF_CLI_CLICK_VERSION\}' 'workflow must install the pinned click version' +require_pattern .github/workflows/deploy-hf-space.yml 'repos settings --help.*grep -- --protected' 'workflow must verify Protected visibility support' require_pattern .github/workflows/deploy-hf-space.yml 'get_space_variables' 'workflow must read Space Variables through HfApi because the pinned CLI has no Settings subcommands' require_pattern .github/workflows/deploy-hf-space.yml 'space_info' 'workflow must read Space metadata through HfApi' if grep -Eq '(^|[^[:alnum:]_.-])hf[[:space:]]+(download|upload|spaces)([[:space:]]|$)' .github/workflows/deploy-hf-space.yml; then