Bind a worker's name and labels into its token; list and revoke tokens by jti

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
This commit is contained in:
2026-10-07 08:42:14 +02:00
co-authored by Claude Opus 5.5
parent 71b0f986e9
commit 21537e2eb6
16 changed files with 470 additions and 38 deletions
+20 -1
View File
@@ -20,7 +20,7 @@ from fluksio.flow.artifacts import is_reference
from fluksio.flow.controller import FlowController
from fluksio.flow.dashboards import DashboardDef, DashboardStore
from fluksio.flow.workers import PythonWorkerPool
from fluksio.models import OAuthClient, TokenPayload, User
from fluksio.models import OAuthClient, TokenPayload, User, WorkerToken
reusable_oauth2 = OAuth2PasswordBearer(
tokenUrl=f"{settings.API_V1_STR}/login/access-token"
@@ -300,6 +300,25 @@ def oauth_client_lives(client_id: str) -> bool:
return session.get(OAuthClient, key) is not None
def worker_claims(token: str) -> dict[str, Any]:
"""A worker credential's claims, if it is still good. Blocking.
Raises ``InvalidTokenError`` for one that does not verify, one minted
before tokens carried a `jti` and their labels, and one a superuser has
revoked. A token whose `jti` has no row is one the engine minted for
itself, a provisioned machine's, and is good until it expires.
"""
claims = security.decode_worker_token(token)
jti = claims.get("jti")
if not jti:
raise InvalidTokenError("this worker token predates revocation; mint a new one")
with Session(engine) as session:
row = session.get(WorkerToken, str(jti))
if row is not None and row.revoked_at is not None:
raise InvalidTokenError("this worker token has been revoked")
return claims
def _gate_agent(payload: dict[str, Any]) -> dict[str, Any]:
"""Refuse a token whose agent has been revoked."""
if not oauth_client_lives(str(payload.get("client_id") or "")):