fix(api-tokens): harden with security fixes, design compliance, and test coverage (#567)

Security: add JWT-level expiry ceiling (400d), per-user token count limit (25),
and token name uniqueness enforcement. Fix async clipboard copy.

Design: migrate Select to Combobox, apply card bevel styling, fix icon
strokeWidth, add tabular-nums to timestamps, fix destructive button pattern.

Tests: expand from ~20 to 47 test cases covering creation validation, token
limits, name uniqueness, last_used_at tracking, ownership constraints, delete
edge cases, and registry blocked endpoints.

Docs: update API Tokens docs with token limits, name uniqueness, registry
restrictions, and JWT expiry ceiling. Update OpenAPI spec with 409 response.
This commit is contained in:
Anso
2026-04-13 18:32:07 -04:00
committed by GitHub
parent 02c2d24004
commit e0d1ca9dc0
8 changed files with 328 additions and 45 deletions
+9 -3
View File
@@ -1303,7 +1303,7 @@ paths:
**Note:** API tokens cannot create other API tokens.
responses:
"201":
description: Token created. The `token` field contains the full JWT — save it now, it won't be shown again.
description: Token created. The `token` field contains the full JWT. Save it now; it will not be shown again.
content:
application/json:
schema:
@@ -1316,13 +1316,19 @@ paths:
type: string
description: Full JWT token. Store securely — this is the only time it's returned.
"400":
description: Validation error.
description: Validation error (missing/invalid fields, or maximum of 25 active tokens reached).
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"403":
$ref: "#/components/responses/Forbidden"
"409":
description: An active token with this name already exists.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"500":
$ref: "#/components/responses/InternalError"
requestBody:
@@ -1335,7 +1341,7 @@ paths:
properties:
name:
type: string
description: Human-readable token name.
description: Human-readable token name. Must be unique among the user's active tokens.
maxLength: 100
example: CI/CD Deploy Token
scope: