fix(ui): skip revoked-key detection until the key list is known

existingKeyIds defaulted to an empty Set, which made every live
api_key row render as (revoked) during the brief window before
apiKeysApi.list() resolved, and permanently after a fetch failure.
Use null as the unknown state and suppress the revoked badge until
the parent provides a real Set.

Refs: #9862
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2026-05-20 23:23:36 +00:00
parent bfd16870d5
commit 72ac1b3334
2 changed files with 10 additions and 6 deletions

View File

@@ -28,8 +28,9 @@ export default function SourcesTab({ period, adminUserId }) {
const [sortKey, setSortKey] = useState('tokens')
// Pull the current set of API key ids so the table can mark unknown keys as
// revoked. Failure is non-fatal: the revoked badge just won't render.
const [existingKeyIds, setExistingKeyIds] = useState(new Set())
// revoked. null = "don't know yet" so the table won't dim live keys during
// the fetch or after a failure.
const [existingKeyIds, setExistingKeyIds] = useState(null)
useEffect(() => {
apiKeysApi
.list()
@@ -37,7 +38,7 @@ export default function SourcesTab({ period, adminUserId }) {
const list = Array.isArray(resp) ? resp : (resp?.keys || [])
setExistingKeyIds(new Set(list.map((k) => k.id)))
})
.catch(() => { /* revoked detection is best-effort */ })
.catch(() => { /* leave existingKeyIds null so revoked detection is skipped */ })
}, [])
useEffect(() => {

View File

@@ -37,7 +37,10 @@ function formatRelative(iso) {
// onSelectKey: (id|null) => void
// search / setSearch: free-text filter state lifted to the parent
// sortKey / setSortKey: sort column state lifted to the parent
// existingKeyIds: Set<string> of current (non-revoked) api key ids
// existingKeyIds: Set<string> of current (non-revoked) api key ids, or null
// when the parent hasn't yet learned which keys exist. Null suppresses the
// revoked badge entirely so live keys aren't dimmed during the fetch or
// after a failure.
export default function SourcesTable({
totals,
selectedKey,
@@ -46,7 +49,7 @@ export default function SourcesTable({
setSearch,
sortKey,
setSortKey,
existingKeyIds = new Set(),
existingKeyIds = null,
}) {
const { t } = useTranslation('admin')
@@ -59,7 +62,7 @@ export default function SourcesTable({
tokens: k.tokens,
requests: k.requests,
last_used: k.last_used,
revoked: !existingKeyIds.has(k.api_key_id),
revoked: existingKeyIds != null && !existingKeyIds.has(k.api_key_id),
}))
const web = totals?.by_source?.web
? [{