Skip to content

fix(rc/0.4.1): hardening from skeptical-QA (put/register/scope/get) - #248

Merged
christophergeyer merged 5 commits into
rc/0.4.1from
cg/rc-041-hardening
Jul 27, 2026
Merged

fix(rc/0.4.1): hardening from skeptical-QA (put/register/scope/get)#248
christophergeyer merged 5 commits into
rc/0.4.1from
cg/rc-041-hardening

Conversation

@christophergeyer

Copy link
Copy Markdown
Member

rc/0.4.1 hardening — fixes from the skeptical-QA pass

A release-gating QA pass over the 0.4.1 candidate (put HF, get --cache, register/scope)
surfaced several confirmed defects — each reproduced, then fixed here with tests. Ranked
by severity below. (The trackio #247 findings are fixed on that PR's branch, not here.)

HIGH — put: don't auto-create HF repos; unify token precedence

  • roar put --private hf://… uploaded bytes to a PUBLIC repo. Root cause + resolution
    (per design discussion): roar was calling create_repo(private=False, exist_ok=True), so
    it created a world-readable repo and made a storage-visibility decision it shouldn't. Now
    roar treats an HF repo like an S3 bucket — it does not create the container and makes
    no visibility call; a missing repo fails with an actionable error. --public/--private
    governs only the GLaaS DAG (below), never storage; storage visibility is the operator's.
  • Upload vs download token precedence was inverted (upload env-first, download file-first)
    → roar could download and upload under different identities. Both are now env-first.

HIGH — register: no false "Secrets: none detected" (#243)

The receipt's secrets line always passed and read "none detected" whenever zero secrets were
recorded — including when the scan never ran (registration.omit.enabled=false), so real
secrets could publish unredacted under a green checkmark. The check now takes secrets_scanned:
a disabled scan fails the line ("lineage was NOT scanned for secrets") instead of claiming
clean. Default config keeps the scan on, so the normal path is unchanged.

MED-HIGH — scope: honor --public/--private for DAG visibility (#240)

Visibility came solely from the bound project's frozen setting, so an explicit --private
on a public project was silently ignored and the DAG went out public. Principle (one rule):
the flag governs the DAG — it may always tighten to private, but may not escalate a
private project to a public DAG (rejected with a clear error). No flag → the scope default.
Wired via a request-scoped contextvar so every lazily-built GlaasClient reconciles consistently.

MED — get --cache: provenance fixes

  • Documented mismatch-fallback now works. A hash mismatch is reported (success=False),
    not raised, so it bypassed the fallback and hard-failed the get. An unsuccessful cache result
    now falls back to the canonical source (still --hash-verified) as the help promises.
  • Prefix provenance. A prefix --cache recorded the bare directory as every file's
    source_url (collapsing AI-BOM downloadLocation to the folder). Each file's mirror URL is
    now remapped onto the canonical prefix → each row records its own canonical object.
  • Warn on --cache without --hash (mirror bytes recorded under the canonical URL unverified).

Tests

New/updated regression tests across test_hf_backend.py, test_publish_auth_context.py,
test_report.py, and test_service.py (get). All touched-area suites green (383 tests);
each fix independently re-verified against its QA repro.

Not included (deliberately)

Base: rc/0.4.1.

chrisgeyertreqs and others added 5 commits July 27, 2026 18:04
High-1 (storage visibility): roar was calling create_repo(private=False,
exist_ok=True), so 'roar put hf://…' silently created a PUBLIC repo — and
'--private' (which only sets DAG visibility) never reached it. roar now
treats the HF repo like an S3 bucket: it does NOT create the container and
makes no visibility decision. A missing repo fails with an actionable error
telling the operator to create it with their intended visibility. Removes
the now-meaningless HFBackend(private=) param.

F3 (token precedence): the upload backend read env-first while the download
backend read ~/.hf_token first, so with both set roar could download and
upload under DIFFERENT identities. Both are now env-first (matches
huggingface_hub's own convention and lets a per-run HF_TOKEN override a
stale token file).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The DAG's scope_request.visibility was derived solely from the bound
project's frozen visibility, so an explicit --private on a PUBLIC project
was silently ignored and the DAG went out public.

Principle (one non-arbitrary rule): the flag governs DAG visibility — it may
always tighten to private, but may not escalate a private project to a public
DAG (rejected with a clear error). No flag -> the scope default (unchanged).

Wiring: the publish builds several GlaasClients lazily/independently, so the
CLI records the explicit choice in a request-scoped contextvar that every
lazily-built client reconciles against (set_requested_publish_visibility);
load_publish_auth_context also takes an explicit requested_public for tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… disabled (#243)

The register receipt's secrets line always passed and its note read 'none
detected' whenever zero secrets were recorded — including when the scan never
ran (registration.omit.enabled=false), so real secrets could publish
unredacted while the checklist gave green false assurance.

The secrets check now takes secrets_scanned: when the scan is disabled the
line fails (ok=False) with 'lineage was NOT scanned for secrets', and the note
says the scan was disabled rather than 'none detected'. Scan-enabled parity
with the execution's own omit_filter gate; default config keeps the scan on,
so the normal path is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ance, warn without --hash

Three --cache provenance fixes from the rc/0.4.1 QA pass:

- B (documented fallback): a hash mismatch is REPORTED as success=False (not
  raised), so it bypassed the fallback try/except and hard-failed the whole get.
  An unsuccessful cache result now triggers the same canonical fallback the
  help text promises (canonical is still --hash-verified).
- D (prefix provenance): a prefix --cache recorded the bare canonical prefix as
  every file's source_url, collapsing AI-BOM downloadLocation to the directory.
  Each file's mirror URL is now remapped onto the canonical prefix, so each row
  records its own canonical object.
- A (unverified provenance): --cache without --hash records mirror bytes under
  the canonical URL unverified; it now warns.

Provenance origin is tracked (fetched_from_cache) so a fallback fetch records
the canonical per-file URL correctly too.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@christophergeyer christophergeyer mentioned this pull request Jul 27, 2026
@christophergeyer
christophergeyer marked this pull request as ready for review July 27, 2026 19:01
@christophergeyer
christophergeyer merged commit f10015f into rc/0.4.1 Jul 27, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants