{"owner":"trycua","repo":"cua","hasSpec":true,"specFile":"libs/fleet/backend/docs/swagger.json","branch":"HEAD","format":"json","version":"2.0","title":"Cyclops CS Backend API","description":"Backend sidecar for the cyclops-cs SPA — Keycloak-authenticated key management, service proxies (k8s / orch / svc), and namespace management. All pool operations use OSGymSandboxClaim CRs (Path B).","pathsCount":18,"endpoints":[{"method":"POST","path":"/api/billing/portal-session","summary":"Create Stripe Billing Portal Session"},{"method":"POST","path":"/api/billing/setup-session","summary":"Create Stripe card setup Session"},{"method":"GET","path":"/api/billing/summary","summary":"Billing summary"},{"method":"POST","path":"/api/billing/webhook","summary":"Receive Stripe webhook"},{"method":"GET","path":"/api/chat/conversations","summary":"List the calling user's chat conversations"},{"method":"POST","path":"/api/chat/conversations","summary":"Create a chat conversation"},{"method":"GET","path":"/api/chat/conversations/{id}","summary":"Get a chat conversation"},{"method":"POST","path":"/api/chat/conversations/{id}/turns","summary":"Send a chat turn and stream the assistant response"},{"method":"GET","path":"/api/config","summary":"Per-user feature flags"},{"method":"GET","path":"/api/k8s/{path}","summary":"Authenticated proxy to the in-pod kubectl-proxy sidecar"},{"method":"GET","path":"/api/keys","summary":"List the calling user's API keys"},{"method":"POST","path":"/api/keys","summary":"Create a new API key"},{"method":"DELETE","path":"/api/keys/{id}","summary":"Revoke an API key by Keycloak client UUID"},{"method":"GET","path":"/api/namespaces","summary":"List the calling user's namespaces"},{"method":"POST","path":"/api/namespaces","summary":"Create a namespace for the calling user"},{"method":"GET","path":"/api/namespaces/{name}","summary":"Get a namespace owned by the calling user"},{"method":"DELETE","path":"/api/namespaces/{name}","summary":"Delete a namespace owned by the calling user"},{"method":"GET","path":"/api/orch/{namespace}/{service}/{path}","summary":"SPA-authenticated proxy to a per-namespace orchestrator service"},{"method":"GET","path":"/api/svc/{namespace}/{service}/{path}","summary":"Authenticated reverse proxy to a K8s Service in a namespace the caller owns"},{"method":"GET","path":"/api/user-keys","summary":"List the calling user's API keys"},{"method":"POST","path":"/api/user-keys","summary":"Create a per-user API key"},{"method":"DELETE","path":"/api/user-keys/{id}","summary":"Revoke a per-user API key"},{"method":"GET","path":"/healthz","summary":"Liveness probe"}],"spec":{"swagger":"2.0","info":{"description":"Backend sidecar for the cyclops-cs SPA — Keycloak-authenticated key management, service proxies (k8s / orch / svc), and namespace management. All pool operations use OSGymSandboxClaim CRs (Path B).","title":"Cyclops CS Backend API","contact":{},"version":"0.1"},"basePath":"/","paths":{"/api/billing/portal-session":{"post":{"security":[{"BearerAuth":[]}],"description":"Creates a Stripe-hosted Billing Portal Session for the customer owned by the authenticated Cyclops subject.","produces":["application/json"],"tags":["billing"],"summary":"Create Stripe Billing Portal Session","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.BillingSessionResponse"}},"400":{"description":"Bad Request","schema":{"type":"object","additionalProperties":{"type":"string"}}},"401":{"description":"Unauthorized","schema":{"type":"object","additionalProperties":{"type":"string"}}},"403":{"description":"Forbidden","schema":{"type":"object","additionalProperties":{"type":"string"}}},"404":{"description":"Not Found","schema":{"type":"object","additionalProperties":{"type":"string"}}},"503":{"description":"Service Unavailable","schema":{"type":"object","additionalProperties":{"type":"string"}}}}}},"/api/billing/setup-session":{"post":{"security":[{"BearerAuth":[]}],"description":"Creates a Stripe-hosted Checkout Session in setup mode for reusable off-session card collection.","produces":["application/json"],"tags":["billing"],"summary":"Create Stripe card setup Session","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.BillingSessionResponse"}},"400":{"description":"Bad Request","schema":{"type":"object","additionalProperties":{"type":"string"}}},"401":{"description":"Unauthorized","schema":{"type":"object","additionalProperties":{"type":"string"}}},"403":{"description":"Forbidden","schema":{"type":"object","additionalProperties":{"type":"string"}}},"503":{"description":"Service Unavailable","schema":{"type":"object","additionalProperties":{"type":"string"}}}}}},"/api/billing/summary":{"get":{"security":[{"BearerAuth":[]}],"description":"Returns a sanitized Stripe-backed billing summary for the authenticated Cyclops subject.","produces":["application/json"],"tags":["billing"],"summary":"Billing summary","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/billing.Summary"}},"401":{"description":"Unauthorized","schema":{"type":"object","additionalProperties":{"type":"string"}}},"403":{"description":"Forbidden","schema":{"type":"object","additionalProperties":{"type":"string"}}},"503":{"description":"Service Unavailable","schema":{"type":"object","additionalProperties":{"type":"string"}}}}}},"/api/billing/webhook":{"post":{"description":"Verifies a Stripe-signed raw webhook body and configures the default payment method for completed fleet setup intents.","consumes":["application/json"],"tags":["billing"],"summary":"Receive Stripe webhook","responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","schema":{"type":"object","additionalProperties":{"type":"string"}}},"413":{"description":"Request Entity Too Large","schema":{"type":"object","additionalProperties":{"type":"string"}}},"502":{"description":"Bad Gateway","schema":{"type":"object","additionalProperties":{"type":"string"}}},"503":{"description":"Service Unavailable","schema":{"type":"object","additionalProperties":{"type":"string"}}}}}},"/api/chat/conversations":{"get":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["chat"],"summary":"List the calling user's chat conversations","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/chat.ConversationSummary"}}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"503":{"description":"Service Unavailable","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}},"post":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["chat"],"summary":"Create a chat conversation","responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/chat.Conversation"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"413":{"description":"Request Entity Too Large","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"503":{"description":"Service Unavailable","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/chat/conversations/{id}":{"get":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["chat"],"summary":"Get a chat conversation","parameters":[{"type":"string","description":"Conversation ID","name":"id","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/chat.Conversation"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"503":{"description":"Service Unavailable","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/chat/conversations/{id}/turns":{"post":{"security":[{"BearerAuth":[]}],"consumes":["application/json"],"produces":["application/x-ndjson"],"tags":["chat"],"summary":"Send a chat turn and stream the assistant response","parameters":[{"type":"string","description":"Conversation ID","name":"id","in":"path","required":true},{"description":"User message or tool results","name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/handlers.TurnRequest"}}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.turnEvent"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"503":{"description":"Service Unavailable","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/config":{"get":{"security":[{"BearerAuth":[]}],"description":"Returns OPA-evaluated feature flags for the authenticated SPA user. `admin` is true when the caller's JWT sub appears in input.flags.admin_subs.","produces":["application/json"],"tags":["config"],"summary":"Per-user feature flags","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.ConfigResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/k8s/{path}":{"get":{"security":[{"BearerAuth":[]}],"description":"Forwards requests to http://127.0.0.1:8001 (the kubectl-proxy sidecar) so the caller can read K8s resources via the pod ServiceAccount. SPA-only; OPA-gated. The policy is an allowlist: only enumerated group/version/resource/method combinations are proxied (the osgym.cua.ai and cua.ai fleet CRDs, namespaced pod/service reads, pod logs and metrics, KubeVirt reads, and API discovery). Anything else, including Kubernetes events and any cluster-scoped path, is denied and never reaches the sidecar.","tags":["passthrough"],"summary":"Authenticated proxy to the in-pod kubectl-proxy sidecar","parameters":[{"type":"string","description":"K8s API path","name":"path","in":"path","required":true}],"responses":{"200":{"description":"K8s API response","schema":{"type":"string"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/keys":{"get":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["keys"],"summary":"List the calling user's API keys","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.ListKeysResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}},"post":{"security":[{"BearerAuth":[]}],"description":"Creates a Keycloak service-account client owned by the calling user. The returned `client_secret` is shown exactly once.","consumes":["application/json"],"produces":["application/json"],"tags":["keys"],"summary":"Create a new API key","parameters":[{"description":"Key parameters","name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/handlers.CreateKeyRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/handlers.CreateKeyResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/keys/{id}":{"delete":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["keys"],"summary":"Revoke an API key by Keycloak client UUID","parameters":[{"type":"string","description":"Keycloak client UUID","name":"id","in":"path","required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/namespaces":{"get":{"security":[{"BearerAuth":[]}],"description":"Returns namespaces owned by the caller's Capsule Tenant. The list is scoped by a capsule.clastix.io/tenant=<tenant> label selector built from the authenticated subject, so it stays fail-closed even when Capsule Proxy isn't filtering.","produces":["application/json"],"tags":["namespaces"],"summary":"List the calling user's namespaces","responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/handlers.NamespaceResponse"}}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}},"post":{"security":[{"BearerAuth":[]}],"description":"Creates a K8s namespace via impersonation. Capsule's webhook intercepts the creation and assigns it to the user's Tenant.","consumes":["application/json"],"produces":["application/json"],"tags":["namespaces"],"summary":"Create a namespace for the calling user","parameters":[{"description":"Namespace parameters","name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/handlers.CreateNamespaceRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/handlers.NamespaceResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"409":{"description":"Conflict","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/namespaces/{name}":{"get":{"security":[{"BearerAuth":[]}],"description":"Gets a K8s namespace via impersonation. Capsule restricts access to the caller's Tenant.","produces":["application/json"],"tags":["namespaces"],"summary":"Get a namespace owned by the calling user","parameters":[{"type":"string","description":"Namespace name","name":"name","in":"path","required":true}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.NamespaceResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}},"delete":{"security":[{"BearerAuth":[]}],"description":"Deletes a K8s namespace via impersonation. Capsule blocks deletion if the namespace doesn't belong to the user's Tenant.","tags":["namespaces"],"summary":"Delete a namespace owned by the calling user","parameters":[{"type":"string","description":"Namespace name","name":"name","in":"path","required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"404":{"description":"Not Found","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/orch/{namespace}/{service}/{path}":{"get":{"security":[{"BearerAuth":[]}],"description":"Resolves <service>.<namespace>.svc.cluster.local at request time (in-cluster DNS). The caller must hold RBAC in {namespace} (verified via an impersonated RoleBinding probe); OPA additionally validates that namespace and service look like DNS-1123 labels.","tags":["passthrough"],"summary":"SPA-authenticated proxy to a per-namespace orchestrator service","parameters":[{"type":"string","description":"Namespace (DNS-1123 label)","name":"namespace","in":"path","required":true},{"type":"string","description":"Service name (DNS-1123 label)","name":"service","in":"path","required":true},{"type":"string","description":"Upstream path","name":"path","in":"path","required":true}],"responses":{"200":{"description":"Upstream response","schema":{"type":"string"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/svc/{namespace}/{service}/{path}":{"get":{"security":[{"BearerAuth":[]}],"description":"Proxies to {service}.{namespace}.svc.cluster.local:80. Per-key tokens are bound to their `namespace` claim; all other principals (SPA, user keys, oauth2-proxy browser sessions) must hold RBAC in {namespace}, verified via an impersonated RoleBinding probe. Strips Authorization before forwarding.","tags":["gateway"],"summary":"Authenticated reverse proxy to a K8s Service in a namespace the caller owns","parameters":[{"type":"string","description":"K8s namespace (caller must own it, or it must match a per-key token's namespace claim)","name":"namespace","in":"path","required":true},{"type":"string","description":"K8s Service name (DNS-1123 label)","name":"service","in":"path","required":true},{"type":"string","description":"Upstream path (proxied verbatim)","name":"path","in":"path"}],"responses":{"200":{"description":"Upstream response","schema":{"type":"string"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"502":{"description":"Bad Gateway","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/user-keys":{"get":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["user-keys"],"summary":"List the calling user's API keys","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.ListUserKeysResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}},"post":{"security":[{"BearerAuth":[]}],"description":"Creates a Keycloak service-account client that acts on behalf of the calling user. The client_secret is returned exactly once; it cannot be retrieved later.","consumes":["application/json"],"produces":["application/json"],"tags":["user-keys"],"summary":"Create a per-user API key","parameters":[{"description":"Key parameters","name":"body","in":"body","required":true,"schema":{"$ref":"#/definitions/handlers.CreateUserKeyRequest"}}],"responses":{"201":{"description":"Created","schema":{"$ref":"#/definitions/handlers.CreateUserKeyResponse"}},"400":{"description":"Bad Request","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/api/user-keys/{id}":{"delete":{"security":[{"BearerAuth":[]}],"produces":["application/json"],"tags":["user-keys"],"summary":"Revoke a per-user API key","parameters":[{"type":"string","description":"Keycloak client UUID","name":"id","in":"path","required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}},"403":{"description":"Forbidden","schema":{"$ref":"#/definitions/handlers.ErrorResponse"}}}}},"/healthz":{"get":{"produces":["application/json"],"tags":["health"],"summary":"Liveness probe","responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/handlers.HealthResponse"}}}}}},"definitions":{"billing.CardSummary":{"type":"object","properties":{"brand":{"type":"string"},"exp_month":{"type":"integer"},"exp_year":{"type":"integer"},"last4":{"type":"string"}}},"billing.Summary":{"type":"object","required":["card","payment_method_present"],"properties":{"card":{"allOf":[{"$ref":"#/definitions/billing.CardSummary"}],"x-nullable":true},"payment_method_present":{"type":"boolean"}}},"chat.Conversation":{"type":"object","properties":{"created_at":{"type":"string"},"id":{"type":"string"},"messages":{"type":"array","items":{"$ref":"#/definitions/chat.Message"}},"title":{"type":"string"},"updated_at":{"type":"string"}}},"chat.ConversationSummary":{"type":"object","properties":{"created_at":{"type":"string"},"id":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string"}}},"chat.Message":{"type":"object","properties":{"content":{"type":"string"},"created_at":{"type":"string"},"id":{"type":"string"},"role":{"$ref":"#/definitions/chat.Role"},"tool_call_id":{"type":"string"},"tool_calls":{"type":"array","items":{"$ref":"#/definitions/chat.ToolCall"}}}},"chat.Role":{"type":"string","enum":["user","assistant","tool"],"x-enum-varnames":["RoleUser","RoleAssistant","RoleTool"]},"chat.ToolCall":{"type":"object","properties":{"function":{"$ref":"#/definitions/chat.ToolFunction"},"id":{"type":"string"},"type":{"type":"string"}}},"chat.ToolFunction":{"type":"object","properties":{"arguments":{"type":"string"},"name":{"type":"string"}}},"handlers.BillingSessionResponse":{"type":"object","properties":{"url":{"type":"string"}}},"handlers.ConfigResponse":{"type":"object","properties":{"admin":{"description":"Admin is true when the caller is in input.flags.admin_subs (OPA-evaluated).\nNon-admins get the customer view: infra-only nav (Nodes, Operator events)\nis hidden in the SPA and the corresponding kubectl-proxy paths are denied\nserver-side by authz.rego.","type":"boolean"},"billing":{"type":"boolean"},"chat":{"type":"boolean"}}},"handlers.CreateKeyRequest":{"type":"object","properties":{"name":{"type":"string","example":"ci-prod"},"namespace":{"type":"string","example":"test-pool"}}},"handlers.CreateKeyResponse":{"type":"object","properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"name":{"type":"string"},"namespace":{"type":"string"},"token_url":{"type":"string"}}},"handlers.CreateNamespaceRequest":{"type":"object","properties":{"name":{"type":"string","example":"my-workspace"}}},"handlers.CreateUserKeyRequest":{"type":"object","properties":{"name":{"type":"string","example":"my-ci-key"},"scope":{"type":"array","items":{"type":"string"},"example":["[\"ns1\"","\"ns2\"]"]}}},"handlers.CreateUserKeyResponse":{"type":"object","properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"name":{"type":"string"},"scope":{"type":"array","items":{"type":"string"}},"token_url":{"type":"string"}}},"handlers.ErrorResponse":{"type":"object","properties":{"error":{"type":"string"}}},"handlers.HealthResponse":{"type":"object","properties":{"ok":{"type":"boolean"}}},"handlers.ListKeysResponse":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/definitions/keycloak.KeyClient"}}}},"handlers.ListUserKeysResponse":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/definitions/handlers.UserKeyResponse"}}}},"handlers.NamespaceResponse":{"type":"object","properties":{"createdAt":{"type":"string"},"labels":{"type":"object","additionalProperties":{"type":"string"}},"name":{"type":"string"},"status":{"type":"string"}}},"handlers.TurnRequest":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/definitions/chat.Message"}}}},"handlers.UserKeyResponse":{"type":"object","properties":{"client_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"scope":{"type":"array","items":{"type":"string"}}}},"handlers.turnEvent":{"type":"object","properties":{"delta":{"type":"string"},"message":{"$ref":"#/definitions/chat.Message"},"type":{"type":"string"}}},"keycloak.KeyClient":{"type":"object","properties":{"client_id":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"namespace":{"type":"string"},"owner_sub":{"type":"string"}}}},"securityDefinitions":{"BearerAuth":{"description":"Keycloak access token. For /api/keys and /api/{k8s,orch} the token is an interactive user JWT (azp=cyclops-cs-spa or azp=cua-cli).","type":"apiKey","name":"Authorization","in":"header"}}}}