Michael Rabinovich commited on
Commit
0bd3c0a
·
1 Parent(s): 7655daf

admin: promote/demote helpers gated by CADGENBENCH_ADMINS

Browse files

adds admin.py with is_admin, promote_row and demote_row. promotion sets
validation_status to validated and records the evidence type; demotion
reverses it and nulls validation_method. row writes reuse
submit._hub_rmw_results so the lock and read-modify-write semantics
match the submit path. the admin set is read from the CADGENBENCH_ADMINS
space variable.

Files changed (1) hide show
  1. admin.py +112 -0
admin.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Admin-tab handlers for the CADGenBench leaderboard Space.
2
+
3
+ Bundle 7: promote a row into the validated tier (recording the evidence
4
+ type) and demote it back. Gating is the ``CADGENBENCH_ADMINS`` Space
5
+ variable (comma-separated HF usernames); :func:`is_admin` is the single
6
+ predicate the UI uses to enable or disable the controls.
7
+
8
+ Row writes go through :func:`submit._hub_rmw_results`, so the
9
+ ``_HUB_LOCK`` + read-modify-write semantics match the submit path
10
+ exactly. There is no second writer of ``results.jsonl`` with its own
11
+ locking story.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import logging
16
+ import os
17
+ from typing import Any
18
+
19
+ import gradio as gr
20
+
21
+ from submit import _hub_rmw_results
22
+
23
+ logger = logging.getLogger(__name__)
24
+
25
+ ADMINS_ENV = "CADGENBENCH_ADMINS"
26
+
27
+ # The evidence types accepted on promotion. Mirrors the
28
+ # `validation_method` enum in cadgenbench-submissions/schema.md and the
29
+ # validation policy doc.
30
+ VALID_METHODS: tuple[str, ...] = ("code", "traces", "api", "manual")
31
+
32
+
33
+ def admin_usernames() -> set[str]:
34
+ """Parse ``CADGENBENCH_ADMINS`` into a set of HF usernames.
35
+
36
+ Comma-separated, whitespace-trimmed, empties dropped. Read fresh on
37
+ each call so flipping the Space variable takes effect without a code
38
+ deploy. Empty or unset yields an empty set, which means no one is an
39
+ admin and the controls stay inert.
40
+ """
41
+ raw = os.environ.get(ADMINS_ENV, "")
42
+ return {part.strip() for part in raw.split(",") if part.strip()}
43
+
44
+
45
+ def is_admin(profile: gr.OAuthProfile | None) -> bool:
46
+ """Return whether *profile* is a logged-in user in the admin set.
47
+
48
+ Logged-out users (``profile is None``) are never admins. With an
49
+ empty admin set no profile qualifies, so the admin controls remain
50
+ disabled for everyone until ``CADGENBENCH_ADMINS`` is populated.
51
+ """
52
+ if profile is None:
53
+ return False
54
+ return profile.username in admin_usernames()
55
+
56
+
57
+ def promote_row(submission_id: str, method: str) -> None:
58
+ """Move a row into the validated tier with the given evidence type.
59
+
60
+ Sets ``validation_status`` to ``"validated"`` and
61
+ ``validation_method`` to *method*. Idempotent: re-promoting an
62
+ already-validated row to the same method lands the same values.
63
+
64
+ Raises:
65
+ ValueError: *method* is not one of :data:`VALID_METHODS`.
66
+ LookupError: no row in ``results.jsonl`` carries *submission_id*.
67
+ """
68
+ if method not in VALID_METHODS:
69
+ raise ValueError(
70
+ f"Unknown validation_method {method!r}; expected one of "
71
+ f"{', '.join(VALID_METHODS)}."
72
+ )
73
+
74
+ def mutate(rows: list[dict[str, Any]]) -> None:
75
+ for row in rows:
76
+ if row.get("submission_id") == submission_id:
77
+ row["validation_status"] = "validated"
78
+ row["validation_method"] = method
79
+ return
80
+ raise LookupError(
81
+ f"No row with submission_id={submission_id!r} in results.jsonl."
82
+ )
83
+
84
+ _hub_rmw_results(
85
+ mutate,
86
+ commit_message=f"promote {submission_id} to validated ({method})",
87
+ )
88
+
89
+
90
+ def demote_row(submission_id: str) -> None:
91
+ """Return a row to the unvalidated tier, clearing ``validation_method``.
92
+
93
+ Sets ``validation_status`` to ``"unvalidated"`` and nulls
94
+ ``validation_method``. Idempotent on an already-unvalidated row.
95
+
96
+ Raises:
97
+ LookupError: no row in ``results.jsonl`` carries *submission_id*.
98
+ """
99
+ def mutate(rows: list[dict[str, Any]]) -> None:
100
+ for row in rows:
101
+ if row.get("submission_id") == submission_id:
102
+ row["validation_status"] = "unvalidated"
103
+ row["validation_method"] = None
104
+ return
105
+ raise LookupError(
106
+ f"No row with submission_id={submission_id!r} in results.jsonl."
107
+ )
108
+
109
+ _hub_rmw_results(
110
+ mutate,
111
+ commit_message=f"demote {submission_id} to unvalidated",
112
+ )