Move New badge to System settings tab (#6963)

* Move New badge to System settings tab

Show the "New" badge on the System tab and drop it from Connections.

* Stabilize refresh revocation UI test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Michael Han 2026-07-08 01:51:34 -07:00 committed by GitHub
parent e7e6a0fb47
commit 7f9964f21e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 50 additions and 10 deletions

View file

@ -56,6 +56,7 @@ const TABS: TabDef[] = [
id: "resources",
labelKey: "settings.tabs.resources",
icon: CpuIcon,
badgeKey: "common.new",
},
{
id: "chat",
@ -72,7 +73,6 @@ const TABS: TabDef[] = [
id: "connections",
labelKey: "settings.tabs.connections",
icon: CloudIcon,
badgeKey: "common.new",
},
{ id: "about", labelKey: "settings.tabs.about", icon: HelpCircleIcon },
];

View file

@ -380,6 +380,18 @@ with sync_playwright() as p:
fail(f"/api/auth/refresh wedged: {refresh_resp['error']!r}")
refresh = refresh_resp.get("body") or {}
token = (refresh or {}).get("access_token")
next_refresh_token = (refresh or {}).get("refresh_token")
if token and next_refresh_token:
robust_evaluate(
page,
"""([accessToken, refreshToken]) => {
localStorage.setItem('unsloth_auth_token', accessToken);
localStorage.setItem('unsloth_auth_refresh_token', refreshToken);
}""",
[token, next_refresh_token],
)
elif token:
fail("/api/auth/refresh returned access_token but no refresh_token")
if not token:
fail("could not obtain auth token after change-password")
@ -1169,6 +1181,13 @@ with sync_playwright() as p:
fail(f"curl login returned no access_token: {login_body!r}")
info("CLI obtained an access token")
browser_refresh_token = robust_evaluate(
page,
"() => localStorage.getItem('unsloth_auth_refresh_token')",
)
if not browser_refresh_token:
fail("browser refresh token missing before CLI rotation")
change_proc = subprocess.run(
[
"curl",
@ -1203,18 +1222,39 @@ with sync_playwright() as p:
# /change-password revoked refresh tokens server-side (auth.py), so
# the browser's /api/auth/refresh must now fail.
refresh_after = evaluate_fetch(
page,
f"{BASE}/api/auth/refresh",
method = "POST",
timeout_ms = FETCH_TIMEOUT_MS,
refresh_proc = subprocess.run(
[
"curl",
"-sS",
"-o",
os.devnull,
"-w",
"%{http_code}",
"-X",
"POST",
f"{BASE}/api/auth/refresh",
"-H",
"Content-Type: application/json",
"-d",
json.dumps({"refresh_token": browser_refresh_token}),
],
capture_output = True,
text = True,
timeout = 15,
)
if refresh_after.get("error"):
fail(f"/api/auth/refresh wedged: {refresh_after['error']!r}")
if refresh_after["status"] == 200:
if refresh_proc.returncode != 0:
fail(
f"curl refresh-token check failed: rc={refresh_proc.returncode} "
f"stderr={refresh_proc.stderr!r} stdout={refresh_proc.stdout!r}"
)
try:
refresh_status = int(refresh_proc.stdout.strip())
except ValueError:
fail(f"curl refresh-token check returned invalid status: " f"{refresh_proc.stdout!r}")
if refresh_status == 200:
fail(f"/api/auth/refresh should fail after CLI rotation; got 200")
info(
f"OK browser /api/auth/refresh now {refresh_after['status']} "
f"OK browser /api/auth/refresh now {refresh_status} "
"(refresh token revoked) -- old studio session can no longer renew"
)