@@ -4,27 +4,74 @@ The public Space is <https://liovina-nl-sql.hf.space>, but it is not currently a
44live demo. The Hugging Face API reports ` PAUSED ` / ` Flagged as abusive `
55(` Cloudflared ` ) since 2026-07-22. Restoring or retiring the deployment is an
66owner-authorized closure action; the policy below describes the safe publish
7- path if restoration is chosen.
7+ path if restoration is chosen. ** Do not re-deploy under an active flag** — wait
8+ until Hugging Face clears the pause, then publish once to prune strays.
9+
10+ ## Deploy script (tracked)
11+
12+ The clean-clone-safe entry point is ** ` scripts/deploy_hf.py ` ** . It is committed,
13+ needs no local kitchen paths, and authenticates only from the process
14+ environment:
15+
16+ | Variable | Role |
17+ | ---| ---|
18+ | ` HF_TOKEN ` | Hugging Face write token for ` HfApi ` |
19+ | ` MISTRAL_API_KEY ` | Value written as the Space secret (never read from a file path) |
20+
21+ Remote mutation requires an ** explicit** ` --apply ` . With no flags the script
22+ prints usage and exits nonzero without touching the network.
23+
24+ ### Local verification (no network, no credentials)
25+
26+ ``` powershell
27+ # From a clean clone / this repo root:
28+ .venv/Scripts/python.exe scripts/deploy_hf.py --self-test
29+ .venv/Scripts/python.exe scripts/deploy_hf.py --dry-run
30+
31+ # Focused tests (also no network):
32+ .venv/Scripts/python.exe -m pytest tests/scripts/test_deploy_hf.py -q
33+ ```
34+
35+ ### Publish (owner-authorized only)
36+
37+ ``` powershell
38+ $env:HF_TOKEN = "<write token>" # process env only
39+ $env:MISTRAL_API_KEY = "<mistral key>" # process env only
40+ .venv/Scripts/python.exe scripts/deploy_hf.py --apply
41+ ```
42+
43+ On ` --apply ` the script: runs the local safety gate → requires both env vars →
44+ skips ` create_repo ` when the Space already exists → sets the Space secret →
45+ uploads only the filtered tracked set → uploads a generated HF-frontmatter
46+ ` README.md ` → prunes remote files that are no longer in the expected set.
847
948## Deploy policy: only what git tracks, then prune
1049
1150The deploy publishes ** exactly the files git tracks** (` git ls-files ` ), never the
1251working tree. Working-kitchen files — internal notes, audits, ` .env ` , scratch
1352reports — are gitignored and a repo-hygiene CI gate fails if any slip into the
1453index, so they cannot reach the Space. The upload also ** prunes** the Space: files
15- removed from the repo are deleted on the host, not left behind from an earlier push.
54+ removed from the repo (or excluded from the publish set) are deleted on the host,
55+ not left behind from an earlier push.
1656
17- The deploy script itself (` .deploy_hf.py ` ) is repo-local (it reads a local token
18- and Mistral key by path) and is intentionally not committed. It:
57+ ` scripts/deploy_hf.py ` does the following:
1958
20591 . computes the file set from ` git ls-files ` minus a publish-exclude list
2160 (` tests/ ` , ` .github/ ` , ` docs/research/ ` , ` reviews/ ` , ` eval/baselines/ ` ,
2261 ` eval/reports/ ` , ` scripts/autotune/ ` );
23- 2 . drops anything the hygiene detector flags;
24- 3 . scans the bytes of the resulting set for tunnel clients and refuses to upload if any
25- are found (see below);
26- 4 . uploads via ` huggingface_hub ` , then prunes remote files no longer present;
27- 5 . supports ` --self-test ` (a gate that runs before upload) and ` --dry-run ` .
62+ 2 . drops anything the hygiene detector (` scripts/check_repo_hygiene.py ` ) flags;
63+ 3 . excludes the repository ` README.md ` from bulk upload (an HF-frontmatter
64+ version is generated, tunnel-marker terms are sanitized, and it is uploaded
65+ separately);
66+ 4 . scans the ** bytes** of every publish file for tunnel clients and refuses to
67+ upload if any are found (see below);
68+ 5 . treats generated ` README.md ` , tracked ` Dockerfile ` , and ` .gitattributes `
69+ (when present) as the expected remote set, then prunes remote strays;
70+ 6 . supports ` --self-test ` and ` --dry-run ` as strictly local modes.
71+
72+ Source-only deployment metadata (` DEPLOY.md ` , ` docs/PROJECT_CLOSURE.md ` , and
73+ ` scripts/deploy_hf.py ` ) is also excluded from the app host: these files document
74+ the tunnel signatures and are not runtime dependencies.
2875
2976The Space hosts the ** app** , not the research record. Eval reports and baselines are
3077260 files / 31 MB the app never reads; they stay in this repo, which is public, and are
@@ -41,17 +88,20 @@ Space was paused under `rule: Cloudflared` minutes after the first deploy that c
4188those notebooks.
4289
4390So the harness is excluded by path, ** and** the deploy scans every file it is about to
44- upload for tunnel markers (` cloudflared ` , ` ngrok ` , ` localtunnel ` , …) and aborts on a hit —
45- the path rule only knows the files that broke once, the content scan covers the rest.
46- ` --self-test ` proves the scanner is not vacuous by planting a marker in a throwaway file
47- and requiring it to be caught.
91+ upload for tunnel markers (` cloudflared ` , ` trycloudflare ` , ` ngrok ` , ` localtunnel ` ,
92+ ` bore.pub ` , ` serveo.net ` , ` pinggy ` , ` loca.lt ` ) in binary chunks with overlap, and aborts
93+ on a hit — the path rule only knows the files that broke once, the content scan covers
94+ the rest. ` --self-test ` proves the scanner is not vacuous by planting a marker in a
95+ throwaway file and requiring it to be caught.
4896
4997## What ships to the Space
5098
5199The Space is ** SQLite-only** — ` psycopg ` is pruned from its ` requirements.txt ` , so
52100the Postgres path (see README) is not present there; it is for local/CI use. The
53- Space carries a subset of the BIRD Mini-Dev databases (the three largest exceed
54- GitHub's 100 MB/file limit and are gitignored):
101+ tracked root ` Dockerfile ` (` python:3.13-slim ` , ` libgomp1 ` , ` PYTHONPATH=/app/src ` ,
102+ Streamlit on ` 0.0.0.0:7860 ` ) is part of the publish set. The Space carries a subset
103+ of the BIRD Mini-Dev databases (the three largest exceed GitHub's 100 MB/file limit
104+ and are gitignored):
55105
56106| DB | size | shipped |
57107| ---| ---| ---|
@@ -75,10 +125,17 @@ the app doesn't re-embed schema chunks on cold start.
75125
76126## Secret
77127
78- The Space needs one secret — ` MISTRAL_API_KEY ` — set in the Space's Settings →
79- Variables and secrets. ` pydantic-settings ` reads it from the environment.
128+ The Space needs one secret — ` MISTRAL_API_KEY ` — set via `scripts/deploy_hf.py
129+ --apply` from the process environment (or manually in the Space's Settings →
130+ Variables and secrets). ` pydantic-settings ` reads it from the environment on the
131+ host. The deploy script never reads or prints local credential file paths.
80132
81133## Updating
82134
83- Re-run the local deploy script; it re-uploads the tracked set and prunes. CI (tests
84- + repo-hygiene) gates ` main ` before any deploy is worth doing.
135+ 1 . Confirm the Space is no longer paused/flagged (owner + HF moderation).
136+ 2 . Run ` --self-test ` / ` --dry-run ` locally.
137+ 3 . Run ` --apply ` with ` HF_TOKEN ` and ` MISTRAL_API_KEY ` in the environment only.
138+
139+ CI (tests + repo-hygiene) gates ` main ` before any deploy is worth doing.
140+ Pushing to GitHub does ** not** update the Space; publish is a separate
141+ ` --apply ` step.
0 commit comments