Skip to content

Commit 741f4b6

Browse files
authored
Implement bundle-only HFS provenance (#9)
* feat: enforce bundle-only HFS provenance * Add exact-head HFS contract CI * feat(hfs): add private candidate deployment profile * fix(hfs): make provenance readable at runtime * fix(hfs): parse runtime checksums by filename * fix(runtime): preserve SigV4 behind private Space auth * fix(deploy): include Space LFS attributes in bundle * fix(runtime): strip platform trace headers before SigV4 * fix(smoke): presign S3 requests behind private Space auth
1 parent af31b9b commit 741f4b6

30 files changed

Lines changed: 1300 additions & 453 deletions

‎.env.example‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# LibreFS HFS v2 local configuration ledger.
2+
# Copy to .env only on a protected local machine. This file is never loaded by
3+
# the container and is not uploaded to Hugging Face. Keep all real values out
4+
# of Git, logs, screenshots, and generated Space bundles.
5+
6+
# Local deployment controls only. Do not register these as Space Settings.
7+
HF_TOKEN=
8+
GH_TOKEN=
9+
10+
# Hugging Face Space Secrets: names are registered in hfs-dev.toml.
11+
MINIO_ROOT_USER=
12+
MINIO_ROOT_PASSWORD=
13+
OPS_TOKEN=
14+
ADMIN_TOKEN=
15+
16+
# Hugging Face Space Variables. Leave a value empty when the code default is
17+
# intended; use a 40-character lowercase SHA for a release LIBREFS_COMMIT.
18+
HFS_RELEASE_BUILD=
19+
LIBREFS_COMMIT=
20+
LIBREFS_REF=
21+
GO_VERSION=
22+
PUBLIC_BASE_URL=
23+
MINIO_SERVER_URL=
24+
MINIO_BROWSER_REDIRECT_URL=
25+
ADMIN_ENABLED=
26+
ADMIN_AUDIT_LOG=
27+
CONTROL_PLANE_DEFAULT_LANG=
28+
MINIO_SITE_NAME=
29+
MINIO_SITE_REGION=
30+
MINIO_BROWSER=
31+
MINIO_BROWSER_REDIRECT=
32+
MINIO_UPDATE=
33+
MINIO_CALLHOME_ENABLE=
34+
MINIO_API_ROOT_ACCESS=
35+
MINIO_API_CORS_ALLOW_ORIGIN=

‎.github/workflows/ci.yml‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: HFS contract
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
verify:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
- name: Validate repository contract
20+
run: scripts/validate-contract.sh
21+
- name: Export and verify exact-head bundle
22+
run: |
23+
set -euo pipefail
24+
scripts/export-space-bundle.sh \
25+
--source-commit "$GITHUB_SHA" \
26+
--librefs-source-commit e194bd779f36fdc08f310d2819d9356f0c1f991b \
27+
--output "$RUNNER_TEMP/librefs-hfs-space"
28+
scripts/verify-space-bundle.sh --bundle "$RUNNER_TEMP/librefs-hfs-space"
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
name: Deploy verified LibreFS HFS wrapper
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
target:
7+
description: "Manifest-owned deployment target"
8+
required: true
9+
default: candidate
10+
type: choice
11+
options: [candidate, production]
12+
confirm_release:
13+
description: "Type RELEASE to confirm the Space write"
14+
required: true
15+
type: string
16+
librefs_commit:
17+
description: "Immutable 40-character lowercase libreFS commit already configured in Space Variables"
18+
required: true
19+
type: string
20+
21+
permissions:
22+
contents: read
23+
24+
concurrency:
25+
group: librefs-hfs-space-release
26+
cancel-in-progress: false
27+
28+
env:
29+
HF_CLI_VERSION: "1.5.0"
30+
31+
jobs:
32+
deploy:
33+
if: ${{ inputs.confirm_release == 'RELEASE' }}
34+
runs-on: ubuntu-24.04
35+
environment: ${{ inputs.target == 'candidate' && 'hfs-candidate' || 'hfs-production' }}
36+
steps:
37+
- name: Check out the immutable wrapper commit
38+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
39+
with:
40+
fetch-depth: 1
41+
42+
- name: Validate release inputs and configured source pin
43+
env:
44+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
45+
LIBREFS_COMMIT: ${{ inputs.librefs_commit }}
46+
HFS_MANIFEST: ${{ inputs.target == 'candidate' && 'hfs-dev.candidate.toml' || 'hfs-dev.toml' }}
47+
run: |
48+
set -Eeuo pipefail
49+
[[ "$LIBREFS_COMMIT" =~ ^[0-9a-f]{40}$ ]]
50+
SPACE_ID="$(python3 -c 'import os,tomllib; print(tomllib.load(open(os.environ["HFS_MANIFEST"], "rb"))["space"])')"
51+
echo "SPACE_ID=$SPACE_ID" >> "$GITHUB_ENV"
52+
python3 -m pip install --disable-pip-version-check "huggingface_hub==${HF_CLI_VERSION}"
53+
if [[ "${{ inputs.target }}" == candidate ]]; then
54+
test "$(hf spaces info "$SPACE_ID" --expand private --json | python3 -c 'import json,sys; print(str(json.load(sys.stdin)["private"]).lower())')" = true
55+
fi
56+
configured_variables="$(hf spaces variables list "$SPACE_ID")"
57+
grep -F "LIBREFS_COMMIT" <<<"$configured_variables" >/dev/null
58+
grep -F "$LIBREFS_COMMIT" <<<"$configured_variables" >/dev/null
59+
grep -E 'HFS_RELEASE_BUILD.*true|true.*HFS_RELEASE_BUILD' <<<"$configured_variables" >/dev/null
60+
61+
- name: Export and verify the allowlisted Space wrapper
62+
env:
63+
HFS_MANIFEST: ${{ inputs.target == 'candidate' && 'hfs-dev.candidate.toml' || 'hfs-dev.toml' }}
64+
run: |
65+
set -Eeuo pipefail
66+
scripts/export-space-bundle.sh \
67+
--source-commit "$GITHUB_SHA" \
68+
--librefs-source-commit "$LIBREFS_COMMIT" \
69+
--manifest "$HFS_MANIFEST" \
70+
--output "$RUNNER_TEMP/librefs-hfs-space-bundle"
71+
scripts/verify-space-bundle.sh --bundle "$RUNNER_TEMP/librefs-hfs-space-bundle"
72+
73+
- name: Refuse a Space repository outside the wrapper boundary
74+
env:
75+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
76+
run: |
77+
set -Eeuo pipefail
78+
bundle_dir="$RUNNER_TEMP/librefs-hfs-space-bundle"
79+
preflight_dir="$RUNNER_TEMP/librefs-hfs-space-preflight"
80+
expected_paths="$(cd "$bundle_dir" && find . -type f -print | LC_ALL=C sort | cut -c3-)"
81+
if ! hf download "$SPACE_ID" --repo-type space --local-dir "$preflight_dir" >/dev/null 2>&1; then
82+
echo "Refusing to upload: unable to read the current Space repository." >&2
83+
exit 1
84+
fi
85+
actual_paths="$(cd "$preflight_dir" && find . -type f ! -path './.cache/huggingface/*' -print | LC_ALL=C sort | cut -c3-)"
86+
if [[ "$actual_paths" != "$expected_paths" ]]; then
87+
printf '%s\n%s\n' \
88+
'Refusing to upload: the current Space repository is not exactly the verified wrapper boundary.' \
89+
'This workflow never deletes legacy files. Migrate to a clean Space repository or perform a separately approved, reviewed cleanup before retrying.' >&2
90+
exit 1
91+
fi
92+
93+
- name: Upload only the verified wrapper bundle
94+
env:
95+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
96+
run: |
97+
set -Eeuo pipefail
98+
hf upload "$SPACE_ID" "$RUNNER_TEMP/librefs-hfs-space-bundle" . \
99+
--repo-type space \
100+
--commit-message "Deploy verified wrapper ${GITHUB_SHA}"
101+
102+
- name: Read back the complete uploaded wrapper and Space metadata
103+
env:
104+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
105+
run: |
106+
set -Eeuo pipefail
107+
bundle_dir="$RUNNER_TEMP/librefs-hfs-space-bundle"
108+
readback_dir="$RUNNER_TEMP/librefs-hfs-space-readback"
109+
expected_paths="$(cd "$bundle_dir" && find . -type f -print | LC_ALL=C sort | cut -c3-)"
110+
if ! hf download "$SPACE_ID" --repo-type space --local-dir "$readback_dir" >/dev/null 2>&1; then
111+
echo "Unable to read back the uploaded Space repository." >&2
112+
exit 1
113+
fi
114+
actual_paths="$(cd "$readback_dir" && find . -type f ! -path './.cache/huggingface/*' -print | LC_ALL=C sort | cut -c3-)"
115+
[[ "$actual_paths" == "$expected_paths" ]]
116+
cmp "$bundle_dir/BUILD_SOURCE.json" "$readback_dir/BUILD_SOURCE.json"
117+
cmp "$bundle_dir/SHA256SUMS" "$readback_dir/SHA256SUMS"
118+
(
119+
cd "$readback_dir"
120+
sha256sum -c SHA256SUMS
121+
)
122+
hf spaces info "$SPACE_ID"
123+
124+
- name: Record remaining runtime owner gates
125+
run: |
126+
cat <<'EOF'
127+
Source bundle upload and complete repository readback succeeded. Before
128+
treating the release as complete, the release and data owners must
129+
separately read back Space build/runtime status and perform the approved
130+
health, authenticated S3 smoke, restart/rebuild persistence, backup, and
131+
isolated-restore checks. This workflow performs none of those actions.
132+
EOF

‎.gitignore‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ __pycache__/
33
.data/
44
*.log
55

6-
# Local environment and secrets.
6+
# Local environment, generated provenance, and secrets.
77
.env
88
.env.*
99
.env.local
1010
!.env.example
1111
!.env.*.example
12+
BUILD_SOURCE.json
13+
SHA256SUMS
14+
config.toml
1215
/local

0 commit comments

Comments
 (0)