"""Pydantic models — GCAP-SPEC-LLM-PRINCIPAL-BROKER-0001 §3, §8.""" from pydantic import BaseModel, Field from typing import Optional from datetime import datetime from enum import Enum from uuid import UUID class DelegationStatus(str, Enum): REQUESTED = "requested" ACTIVE = "active" EXPIRED = "expired" REVOKED = "revoked" class DelegationScope(BaseModel): inherit_corpus: bool = True inherit_contexts: bool = True capability_ceiling: str = "CAP_MUTATE" ceremony_required_for: list[str] = Field( default_factory=lambda: ["delete", "destroy", "drop"] ) prohibited_commands: list[str] = Field(default_factory=list) max_ttl_minutes: int = 60 max_commands: int = 500 class DelegationRequest(BaseModel): """POST /delegate request body — §8.1.""" delegator_ac_id: str agent_type: str = "claude-code" agent_model: Optional[str] = None scope: Optional[DelegationScope] = None accord_template: str = "ai-delegation-standard" class AgentPrincipal(BaseModel): did: str keycloak_client_id: str display_name: str class DelegatedAC(BaseModel): context_id: str delegator_did: str agent_did: str capability_ceiling: str expires_at: str delegation_chain: list[dict] class DelegationResponse(BaseModel): """POST /delegate response — §3.2.""" delegation_id: str agent_principal: AgentPrincipal delegated_ac: dict agent_token: str expires_at: str max_commands: int chronicle_cid: Optional[str] = None class DelegationInfo(BaseModel): """GET /delegate/{id} response — §8.3.""" delegation_id: str status: DelegationStatus agent_did: str agent_type: str delegator_did: str commands_executed: int commands_remaining: int ttl_remaining_seconds: int created_at: str expires_at: str class RevokeRequest(BaseModel): reason: str = "manual_revocation" class RevokeResponse(BaseModel): delegation_id: str status: str = "revoked" reason: str chronicle_cid: Optional[str] = None class ActiveDelegation(BaseModel): delegation_id: str agent_type: str delegator: str commands_executed: int ttl_remaining_seconds: int status: str class AgentListResponse(BaseModel): active_delegations: list[ActiveDelegation] total_active: int