Spaces:
Runtime error
title: AV Causal Scenario Retrieval Challenge
emoji: 🔍
colorFrom: green
colorTo: gray
sdk: docker
app_port: 7860
pinned: false
hf_oauth: true
hf_oauth_expiration_minutes: 480
hf_oauth_scopes:
- contribute-repos
AV Causal Scenario Retrieval Challenge
Public challenge site, authenticated submission intake, personal status history,
and leaderboard for the NVIDIA AV Causal Scenario Retrieval Challenge. The
landing page at / presents the challenge overview; the focused participation
page at /participate presents the public leaderboard first, followed by the
submission form and private submission history. /terms explains the exact
versioned consent linked from the submission form.
The Space is a Docker/FastAPI application. It keeps the original public HTML and CSS presentation while exposing six same-origin endpoints:
GET /api/mereturns the current HF username, locked participant profile (if established), artifact repository, and a session-bound CSRF token.POST /api/artifact-repositoriescreates or reconnects the participant's one reusable private app-created model repository.POST /api/submissionsaccepts publicteam, privatecontact_email, privateinstitution, andterms_accepted: true. The first durable intake atomically locks team and institution; later requests must match before handoff begins.POST /api/submissions/<id>/ingestretries handoff of the existing immutable row without creating or charging another submission.GET /api/submissionsreturns only the authenticated user's sanitized rows.GET /api/leaderboardreturns the public materialized leaderboard fetched server-side from the private controller.
The unique participant identity is the rename-safe OAuth sub claim, derived
from the signed Hugging Face session and stored privately as submitter_hf_id.
The current preferred_username is retained as submitter_hf_user for the
participant-owned artifact namespace. The first durable intake under this
profile policy locks the public team display text and private institution
to that stable subject; neither username nor team is used for ownership or
quota checks. The browser cannot supply either HF identity, status, score, consent
version/timestamp, or submission id. /api/me, personal status, results, and
rendered pages never expose the raw stable ID. The additional
least-privilege contribute-repos scope can access only repositories created by
this OAuth app. The access token travels only in the signed OAuth session and
the transient ingestion handoff; it is never logged, written to challenge
datasets/results, or returned by an application API.
Official inference uses one NVIDIA A100 80 GB GPU with compute capability
sm_80. Participant CUDA/PyTorch binaries must include sm_80 kernels. The
participation page states this requirement, and legacy generic inference errors
are rendered with an actionable entrypoint/GPU-compatibility check; true
time-limit failures are reported separately by the controller. Challenge rules
require the participant entrypoint to complete within six hours. The
evaluator's higher operational fail-safe and outer Job deadline are
infrastructure-only grace for trusted setup, validation, and output flushing;
they do not provide extra participant runtime.
institution must name the participant's current university, company,
research lab, nonprofit, government, or comparable formal affiliation.
Independent, unaffiliated, and other explicit no-affiliation placeholders are
rejected in both the browser and server. This is a participant attestation;
string validation does not independently verify employment or enrollment.
The exact schema-v3 request written to the private intake dataset is:
{
"schema_version": 3,
"submission_id": "server-generated-uuid",
"team": "Public Team Name",
"submitter_hf_id": "private-rename-safe-oauth-sub",
"submitter_hf_user": "oauth-username",
"artifact_repo_id": "oauth-username/private-model-repo",
"contact_email": "Private@example.org",
"institution": "Private Institution",
"terms_accepted": true,
"terms_version": "2026-06-30-v4",
"terms_accepted_at": "server-generated UTC timestamp",
"track": "main",
"submitted_at": "same server-generated UTC timestamp",
"status": "QUEUED"
}
Consent evidence deliberately excludes IP addresses, user agents, OAuth tokens,
and other browser fingerprints. Contact email, institution, and consent fields
remain in private intake/controller storage and are omitted from status mirrors,
results, and the public leaderboard. Authenticated /api/me returns only the
participant's own locked team and institution so the form can enforce them; it
never returns contact email or the raw stable ID. /api/me also binds the current
terms version to the signed session, and intake rejects a stale session after a
terms-version change until the participant refreshes and reviews the new terms.
Schema-3 personal-history filtering uses exact stable-ID equality. Only legacy
schema-2 status rows fall back to case-insensitive username matching.
Space configuration
Add these required Space secrets:
CHALLENGE_FRONTEND_TOKEN: a fine-grained service token restricted to read and writenvidia/crc-submission-intake. It must not access the controller-owned state dataset, hidden datasets, participant repositories, Jobs, or results.CHALLENGE_BACKEND_TOKEN: a distinct fine-grained read-only HF gateway credential limited to the private controller Space. The frontend uses it server-side for ingestion handoff and leaderboard reads. It must never be the broadHF_CONTROLLER_TOKENused by the controller itself.CHALLENGE_INGEST_SECRET: independent shared secret checked by the backend ingestion endpoint (at least 32 random bytes).
Optional Space variables:
CHALLENGE_INTAKE_REPO(defaultnvidia/crc-submission-intake)CHALLENGE_STATUS_REPO(defaultnvidia/crc-submission-intake)CHALLENGE_BACKEND_URL(clean HTTPS private-controller origin with no path, credentials, query, or fragment; required for ingestion)CHALLENGE_BACKEND_ALLOWED_HOST(defaultnvidia-av-causal-retrieval-challenge-backend.hf.space; the URL must match it exactly before any credential is sent)CHALLENGE_TERMS_VERSION(default2026-06-30-v4; must match the controller'sCRC_TERMS_VERSIONand the bundledterms.html; deployed startup fails if the frontend variable does not match the bundled document, and all versions must be bumped together whenever terms change)CHALLENGE_PUBLIC_ORIGIN(normally inferred fromSPACE_HOST)CHALLENGE_INTAKE_LIMIT(default5)CHALLENGE_INTAKE_WINDOW_SECONDS(default60)CHALLENGE_MAX_INTAKE_BODY_BYTES(default4096)CHALLENGE_MIN_OAUTH_REMAINING_MINUTES(default180; covers the two-hour ingestion timeout plus scheduling margin)CHALLENGE_PARTICIPANT_SCOPE(defaults toSPACE_ID; keep it fixed to the exact Space id so staging and production OAuth apps use different repository names and mapping records)
The frontend writes immutable requests at intake/<submission_id>.json and
reads controller-published, sanitized mirrors from status/<submission_id>.json.
Those mirrors share the intake repository and are explicitly non-authoritative;
the controller never trusts them. Authoritative controller state and results
live behind the private controller and datasets that the frontend intake token
cannot access. For the public same-origin leaderboard endpoint, the frontend
server performs an allowlisted GET /api/leaderboard to the private controller
using only CHALLENGE_BACKEND_TOKEN; it does not send the ingestion secret on
that read. The gateway token is never returned to the browser. The frontend
never receives labels, Job credentials, evaluator logs, or raw exceptions.
One deterministic mapping per stable OAuth subject and OAuth app is stored
privately under participants/. The browser cannot choose or replace the
repository. A separate private profiles/ pointer references the immutable
first intake that locked team and institution, without duplicating institution
PII. The first profile pointer and intake row are one parent-revision-guarded Hub
commit, so concurrent claims cannot select different values. App-scoped names
prevent staging from claiming production repositories or browser preferences.
After the durable commit, the OAuth token is sent transiently to the private
backend in {record, oauth_access_token} with gateway and ingestion-secret
headers. If handoff fails, the existing row remains visible as retryable and a
retry never writes another intake row.
The browser sends a random Idempotency-Key for initial submission creation and
retains it with only a SHA-256 form fingerprint in session storage until the
server confirms the immutable intake. Contact fields are not stored there. The
server derives a participant-bound submission UUID from that key, so an
ambiguous Hub commit response can be retried without creating a second row.
If the participant selects “Remember this email in this browser,” the browser
stores only that editable email in local storage after a confirmed submission.
The key uses the stable app-scoped repository suffix already returned to the
participant, not the mutable username or raw stable ID. Team and institution
come only from authenticated /api/me after locking; neither is browser lock
evidence. Consent, tokens, and the raw stable identity are never stored in this
preference.
The intake limiter is an in-process burst guard; durable attempt limits remain controller-enforced. Submission status reads cache a bounded Hub snapshot at an exact dataset revision and refresh only when that revision changes. In a deployed OAuth Space, startup fails closed if any required credential is missing, the ingestion secret is too short, or the backend URL misses the exact host allowlist.
Do not change the consent clauses in the submission form or terms.html while
reusing an existing terms version. Before production, define retention and
erasure procedures for the Git-backed private intake/state datasets; deleting a
file only from the latest revision does not remove its historical commits.
Local development
Install dependencies and run the app:
python -m pip install -r requirements-dev.txt
uvicorn app:app --reload --port 7860
Outside a Space, the Hugging Face helper uses its documented mock OAuth flow and
the locally authenticated HF account (hf auth login). Keep
CHALLENGE_FRONTEND_TOKEN separate and least-privileged. To inspect only public
routes without any OAuth setup, set CHALLENGE_DISABLE_OAUTH=1; submissions and
personal history remain unavailable in that mode.
Run the checks with:
pytest -q
node validate-static.mjs
docker build -t crc-frontend .