You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ak...@apache.org on 2026/10/06 01:54:10 UTC
(tooling-llmao) 23/23: requests: show what was granted, and log who revoked a key
This is an automated email from the ASF dual-hosted git repository.
andrewmusselman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-llmao.git
commit d411fada77844a9a3f4225f6fd7ce9cca4188a87
Author: Andrew Musselman <ak...@apache.org>
AuthorDate: Tue Oct 6 01:01:44 2026 +0000
requests: show what was granted, and log who revoked a key
THREE SMALL THINGS
"My requests" rendered wanted_h on every row, so a request asked at 20M and
approved at 30M showed 20M -- the one number the requester does not need once
it has been answered. It now shows the grant, with the ask beside it only
when they differ: "30M, asked 30M" is noise on every unmodified approval.
The adjust field said "adjust", which does not say what putting a number
there does. It now says "approve this instead", and the reason field says why
it is sometimes required rather than just that it is.
REVOCATION IS LOGGED
The authz was already right: admin_of is PMC membership, so any PMC member
can already revoke their project's service keys -- not only whoever created
one. A credential the project owns and cannot stop, because the creator is
away at 2am, was never the behaviour here.
What was missing is the record. A key that stops working generates a
question, and "revoked by akm, PMC member of tooling" answers it in one line
instead of starting an investigation. That matters more for service keys than
personal ones precisely because any PMC member can do it, so the person
asking is often not the person who did it.
---
llmao/seam.py | 30 ++++++++++++++++++++++++++++++
pages.py | 3 +++
templates/keys.ezt | 2 +-
templates/requests.ezt | 7 ++++---
tests/test_requests.py | 24 ++++++++++++++++++++++++
5 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/llmao/seam.py b/llmao/seam.py
index 646e1f1..ef0963c 100644
--- a/llmao/seam.py
+++ b/llmao/seam.py
@@ -26,6 +26,7 @@ The seam speaks **project** only; mapping to LiteLLM team_id is the backend's jo
from __future__ import annotations
import functools
+import logging
from dataclasses import dataclass, field
from typing import Any
@@ -43,6 +44,28 @@ from .litellm_client import (
)
+def _log_revocation(identity: Identity, key: KeyInfo, basis: str) -> None:
+ """Record who killed a key, and on what authority.
+
+ A key that stops working generates a question, and the answer is usually
+ "someone revoked it" -- which takes an investigation to establish and one
+ log line to answer. Service keys can be revoked by any PMC member, so the
+ person asking is often not the person who did it.
+ """
+ _LOGGER.info(
+ "key revoked: token=%s purpose=%r project=%s owner=%s by=%s (%s)",
+ (key.token_id or "")[:12],
+ key.purpose or "",
+ key.project or "-",
+ key.user or "-",
+ identity.uid,
+ basis,
+ )
+
+
+_LOGGER = logging.getLogger("llmao")
+
+
class AuthzError(Exception):
"""Caller is not allowed to perform this action on the project."""
@@ -614,14 +637,21 @@ class Seam:
raise AuthzError("key not found or not visible")
if match.user == identity.uid:
await self._backend.delete_key(token_id)
+ _log_revocation(identity, match, "own key")
return
if match.is_automation:
project = match.project
if identity.is_site_admin:
await self._backend.delete_key(token_id)
+ _log_revocation(identity, match, "site admin")
return
+ # Any PMC member, not only whoever created it. A service key
+ # belongs to the project, and a credential the project owns and
+ # cannot stop -- because the creator is away at 2am -- is the
+ # failure mode worth avoiding.
if project and identity.admin_of(project):
await self._backend.delete_key(token_id)
+ _log_revocation(identity, match, f"PMC member of {project}")
return
raise AuthzError("not allowed to revoke this key")
diff --git a/pages.py b/pages.py
index 2eb865c..c57163a 100644
--- a/pages.py
+++ b/pages.py
@@ -970,6 +970,9 @@ def _request_rows(reqs) -> list:
"is_denied": ezt.boolean(r.state == "denied"),
"is_capacity": ezt.boolean(r.kind == "capacity"),
"actionable": ezt.boolean(r.is_actionable()),
+ # Only worth showing the ask when it differs. "30M, asked
+ # 30M" is noise on every approved-as-requested row.
+ "was_adjusted": ezt.boolean(bool(r.granted) and r.granted != r.wanted),
"decision_reason": r.decision_reason,
"decided_by": r.decided_by,
# The question a requester actually has: how long have I
diff --git a/templates/keys.ezt b/templates/keys.ezt
index 621280c..788edc9 100644
--- a/templates/keys.ezt
+++ b/templates/keys.ezt
@@ -119,7 +119,7 @@
<div>
[if-any my_requests.granted_h]
<span class="font-monospace">[my_requests.granted_h]</span>
- [if-any my_requests.is_approved]
+ [if-any my_requests.was_adjusted]
<span class="small text-muted">· asked [my_requests.wanted_h]</span>
[end]
[else]
diff --git a/templates/requests.ezt b/templates/requests.ezt
index 5adc989..0100d5f 100644
--- a/templates/requests.ezt
+++ b/templates/requests.ezt
@@ -41,13 +41,14 @@
[if-any requests.is_capacity]
<div class="col-auto">
<input class="form-control form-control-sm" type="text"
- name="granted_token_cap" placeholder="adjust"
- aria-label="Adjusted allocation" style="width:9rem">
+ name="granted_token_cap" placeholder="approve this instead"
+ aria-label="Approve a different allocation" style="width:12rem">
</div>
[end]
<div class="col">
<input class="form-control form-control-sm" type="text"
- name="reason" placeholder="Reason (required to adjust or deny)"
+ name="reason"
+ placeholder="Why — required if you change the number or deny"
aria-label="Reason">
</div>
<div class="col-auto">
diff --git a/tests/test_requests.py b/tests/test_requests.py
index a07d591..2cac6cd 100644
--- a/tests/test_requests.py
+++ b/tests/test_requests.py
@@ -295,3 +295,27 @@ def test_granted_carries_everything_asked_for_plus_what_was_added():
r = _key()
r.decide(state=STATE_APPROVED, by="admin", granted={"token_cap": 500_000})
assert set(r.granted) == {"purpose", "tier", "token_cap"}
+
+
+def test_an_approved_as_asked_request_has_granted_equal_to_wanted():
+ """So the UI can tell "approved as asked" from "approved, but".
+
+ A row reading "30M, asked 30M" is noise on every unmodified approval;
+ one reading "30M, asked 40M" is the thing the requester needs to see.
+ """
+ r = _capacity()
+ r.decide(state=STATE_APPROVED, by="admin")
+ assert r.granted == r.wanted
+
+
+def test_an_adjusted_request_differs_from_what_was_asked():
+ r = _capacity()
+ r.decide(
+ state=STATE_APPROVED,
+ by="admin",
+ granted={"token_cap": 30_000_000},
+ reason="fleet is heavily committed",
+ )
+ assert r.granted != r.wanted
+ assert r.granted["token_cap"] == 30_000_000
+ assert r.wanted["token_cap"] == 40_000_000
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org