638 lines
28 KiB
YAML
638 lines
28 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: VerseVDI control contract
|
|
version: 1.0.0
|
|
description: Bounded control-plane wire contract. The current SessionRequest shape is control wire version 2; no provider or media endpoints.
|
|
servers:
|
|
- url: /
|
|
tags:
|
|
- name: authentication
|
|
- name: resources
|
|
- name: broker
|
|
- name: events
|
|
- name: session-quality
|
|
- name: gateway
|
|
paths:
|
|
/api/v1/auth/login:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: loginBrowserSession
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/LoginRequest
|
|
responses:
|
|
'200':
|
|
description: Browser session established through secure cookies; native identity is structurally forbidden.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/BrowserAuthenticatedSession
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'503': {$ref: '#/components/responses/Unavailable'}
|
|
/api/v1/auth/refresh:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: rotateNativeCredential
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/RefreshRequest
|
|
responses:
|
|
'200':
|
|
description: Rotated opaque native credential.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/NativeCredential
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/session:
|
|
get:
|
|
tags: [authentication]
|
|
operationId: getAuthenticatedSession
|
|
security:
|
|
- browserSession: []
|
|
- nativeBearer: []
|
|
responses:
|
|
'200':
|
|
description: Route-context-specific authenticated subject summary. Browser responses forbid native identity; native bearer responses require it.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
oneOf:
|
|
- $ref: ../schemas/control-v1.schema.json#/$defs/BrowserAuthenticatedSession
|
|
- $ref: ../schemas/control-v1.schema.json#/$defs/NativeAuthenticatedSession
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/tunnel-credentials:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: issueNativeTunnelCredential
|
|
security:
|
|
- nativeBearer: []
|
|
responses:
|
|
'200':
|
|
description: Short-lived native tunnel credential. The response must not be stored.
|
|
headers:
|
|
Cache-Control:
|
|
description: Prevent storage of the credential response.
|
|
required: true
|
|
schema: {type: string, const: no-store}
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/NativeTunnelCredential
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/reauth:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: issueReauthenticationGrant
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ReauthRequest
|
|
responses:
|
|
'200':
|
|
description: Short-lived opaque step-up grant.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ReauthGrant
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/logout:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: logoutSession
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
- nativeBearer: []
|
|
responses:
|
|
'204': {description: Session revoked and browser cookies cleared.}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/devices:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: registerDevice
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/DeviceRegistrationRequest
|
|
responses:
|
|
'201':
|
|
description: Single-use device challenge.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/DeviceChallenge
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/devices/{device_id}/prove:
|
|
post:
|
|
tags: [authentication]
|
|
operationId: proveDevice
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/DeviceID'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/DeviceProofRequest
|
|
responses:
|
|
'200':
|
|
description: Opaque native credential.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/NativeCredential
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/auth/devices/{device_id}:
|
|
delete:
|
|
tags: [authentication]
|
|
operationId: revokeDevice
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/DeviceID'
|
|
responses:
|
|
'204': {description: Device and its native authority revoked.}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/resources:
|
|
get:
|
|
tags: [resources]
|
|
operationId: listResources
|
|
security:
|
|
- browserSession: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/Limit'
|
|
- $ref: '#/components/parameters/Cursor'
|
|
responses:
|
|
'200':
|
|
description: Subject-scoped bounded resources and entitlements.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ResourceList
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/broker/sessions:
|
|
post:
|
|
tags: [broker]
|
|
operationId: requestBrokerSession
|
|
description: Control wire version 2 endpoint. Legacy version-1 SessionRequest payloads containing client-supplied policy_snapshot are rejected.
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/IdempotencyKey'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/SessionRequest
|
|
responses:
|
|
'201':
|
|
description: Durable broker session.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/BrokerSession
|
|
'202':
|
|
description: Durable session waiting for an eligible desktop or capacity.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/BrokerSession
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'403': {$ref: '#/components/responses/Forbidden'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}:
|
|
get:
|
|
tags: [broker]
|
|
operationId: getBrokerSession
|
|
security:
|
|
- browserSession: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/SessionID'
|
|
responses:
|
|
'200':
|
|
description: Subject-scoped broker session projection.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/BrokerSession
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/broker/sessions/{session_id}/allocate:
|
|
post:
|
|
tags: [broker]
|
|
operationId: allocateBrokerSession
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/SessionID'
|
|
responses:
|
|
'200':
|
|
description: Gateway-only launch manifest with a single-use grant.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ConnectionManifest
|
|
'202':
|
|
description: Session remains waiting for an eligible desktop or capacity.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/BrokerSession
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}/reconnect:
|
|
post:
|
|
tags: [broker]
|
|
operationId: reconnectBrokerSession
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/SessionID'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ReconnectRequest
|
|
responses:
|
|
'200':
|
|
description: Gateway-only reconnect manifest with a monotonic sequence.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ConnectionManifest
|
|
'202':
|
|
description: >-
|
|
Confirmed over-cap reconnect creates or returns a durable `session.display_relaunch` termination operation.
|
|
Before initial operation creation and on every replay, the authenticated principal and active client device/key MUST
|
|
match the broker session. Under the session and unique Stop lock, the Server MUST create at most one termination
|
|
operation total per broker session. A same-owner/device lost-response retry MUST return that same operation.
|
|
If a user Stop wins first, reconnect MUST return a stable non-202 result. If display relaunch wins first, a later user
|
|
Stop MUST converge on that same existing `StopOperation` without creating a second operation or issuing a second Terminate.
|
|
The operation reuses the existing one-way non-reissued Stop work/ack path. This response is not a manifest, does not
|
|
assert termination completion, and does not authorize a replacement session before `applied`.
|
|
After `applied`, the client submits a fresh `SessionRequest` with a new idempotency key.
|
|
Failed or `termination_unconfirmed` outcomes never auto-relaunch. Client local Stop or teardown MUST invalidate
|
|
relaunch generation so a later `applied` state cannot cause a fresh launch.
|
|
Maximum JSON body: 16384 bytes.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/StopOperation
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}/cancel:
|
|
post:
|
|
tags: [broker]
|
|
operationId: cancelBrokerSession
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/SessionID'
|
|
responses:
|
|
'204': {description: Cancellation accepted idempotently.}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/session-quality-limits:
|
|
get:
|
|
tags: [session-quality]
|
|
operationId: getSessionQualityLimits
|
|
security: [{nativeBearer: []}]
|
|
responses:
|
|
'200': {description: 'Current global native session quality limits. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/SessionQualityLimits}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
/api/v1/session-quality-limits/assignments/{assignment_id}:
|
|
get:
|
|
tags: [session-quality]
|
|
operationId: getAssignmentSessionQualityLimits
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/AssignmentID'}]
|
|
responses:
|
|
'200': {description: 'Current assignment-specific native session quality limits. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/SessionQualityLimits}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/session-quality-limits/pools/{pool_id}:
|
|
get:
|
|
tags: [session-quality]
|
|
operationId: getPoolSessionQualityLimits
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/PoolID'}]
|
|
responses:
|
|
'200': {description: 'Current pool-specific native session quality limits. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/SessionQualityLimits}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/admin/entitlements/{entitlement_id}/display-limit-override:
|
|
patch:
|
|
tags: [session-quality]
|
|
operationId: updateEntitlementDisplayLimitOverride
|
|
security:
|
|
- browserSession: []
|
|
browserCsrfCookie: []
|
|
browserCsrfHeader: []
|
|
parameters: [{$ref: '#/components/parameters/EntitlementID'}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/DisplayLimitOverrideRequest}}}}
|
|
responses:
|
|
'204': {description: Direct entitlement display override updated.}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'403': {$ref: '#/components/responses/Forbidden'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}/quality-changes:
|
|
post:
|
|
tags: [session-quality]
|
|
operationId: createSessionQualityChange
|
|
description: The owning principal and active device/key MUST match the subject-scoped broker session. Maximum JSON body: 16384 bytes.
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/SessionID'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/QualityChangeRequest}}}}
|
|
responses:
|
|
'201': {description: 'Durable quality change created. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/QualityChangeOperation}}}}
|
|
'200': {description: 'Existing idempotent quality change returned. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/QualityChangeOperation}}}}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}/quality-changes/{operation_id}:
|
|
get:
|
|
tags: [session-quality]
|
|
operationId: getSessionQualityChange
|
|
description: The owning principal and active device/key MUST match the subject-scoped broker session and operation. Maximum JSON body: 16384 bytes.
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/SessionID'}, {$ref: '#/components/parameters/OperationID'}]
|
|
responses:
|
|
'200': {description: 'Durable quality change state. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/QualityChangeOperation}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/broker/sessions/{session_id}/stop-operations:
|
|
post:
|
|
tags: [session-quality]
|
|
operationId: createSessionStopOperation
|
|
description: The owning principal and active device/key MUST match the subject-scoped broker session. Maximum JSON body: 16384 bytes.
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/SessionID'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
|
responses:
|
|
'201': {description: 'Durable Stop operation created. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/StopOperation}}}}
|
|
'200': {description: 'Existing idempotent Stop operation returned. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/StopOperation}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/broker/sessions/{session_id}/stop-operations/{operation_id}:
|
|
get:
|
|
tags: [session-quality]
|
|
operationId: getSessionStopOperation
|
|
description: The owning principal and active device/key MUST match the subject-scoped broker session and operation. Maximum JSON body: 16384 bytes.
|
|
security: [{nativeBearer: []}]
|
|
parameters: [{$ref: '#/components/parameters/SessionID'}, {$ref: '#/components/parameters/OperationID'}]
|
|
responses:
|
|
'200': {description: 'Durable Stop operation state. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/StopOperation}}}}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'404': {$ref: '#/components/responses/NotFound'}
|
|
/api/v1/gateway/quality-work:
|
|
post:
|
|
tags: [gateway]
|
|
operationId: acquireGatewayQualityWork
|
|
description: The authenticated gateway mTLS certificate identity MUST match `gateway_id`; Server authority MUST match the session, gateway, reconnect sequence, and supplied operation/revision/lease generation coordinates. A `poll` acquisition omits unknown operation coordinates and discovers pending session work after a lost prompt; `prompt` and `observation` coordinates MUST match exactly. Maximum JSON body: 16384 bytes.
|
|
security: [{gatewayMutualTLS: []}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayQualityWorkRequest}}}}
|
|
responses:
|
|
'200': {description: 'Leased quality work or reconciliation observation. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayQualityWork}}}}
|
|
'204': {description: No matching work is available.}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/gateway/quality-ack:
|
|
post:
|
|
tags: [gateway]
|
|
operationId: acknowledgeGatewayQualityWork
|
|
description: The authenticated gateway mTLS certificate identity MUST match `gateway_id`; Server authority MUST exactly match the session, gateway, reconnect sequence, operation, revision, and monotonic lease generation tuple. Stale lease generations MUST be rejected. `applied` requires `current_applied_revision == revision`; `proven_prior` requires `current_applied_revision < revision`; `unknown` forbids `current_applied_revision` and makes no applied-revision assertion. Maximum JSON body: 16384 bytes.
|
|
security: [{gatewayMutualTLS: []}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayQualityAck}}}}
|
|
responses:
|
|
'204': {description: Quality acknowledgement committed idempotently.}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/gateway/stop-work:
|
|
post:
|
|
tags: [gateway]
|
|
operationId: acquireGatewayStopWork
|
|
description: The authenticated gateway mTLS certificate identity MUST match `gateway_id`; Server authority MUST match the session, gateway, reconnect sequence, and any supplied operation coordinate. A `poll` acquisition omits the unknown operation ID and discovers pending session work after a lost prompt; a `prompt` coordinate MUST match exactly. Maximum JSON body: 16384 bytes.
|
|
security: [{gatewayMutualTLS: []}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayStopWorkRequest}}}}
|
|
responses:
|
|
'200': {description: 'One-way non-reissued Stop work claim. Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayStopWork}}}}
|
|
'204': {description: No matching Stop work is available.}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/gateway/stop-ack:
|
|
post:
|
|
tags: [gateway]
|
|
operationId: acknowledgeGatewayStopWork
|
|
description: The authenticated gateway mTLS certificate identity MUST match `gateway_id`; Server authority MUST exactly match the session, gateway, reconnect sequence, and operation tuple. Maximum JSON body: 16384 bytes.
|
|
security: [{gatewayMutualTLS: []}]
|
|
requestBody: {required: true, description: 'Maximum JSON body: 16384 bytes.', content: {application/json: {schema: {$ref: ../schemas/control-v1.schema.json#/$defs/GatewayStopAck}}}}
|
|
responses:
|
|
'204': {description: Stop acknowledgement committed idempotently.}
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
/api/v1/events:
|
|
get:
|
|
tags: [events]
|
|
operationId: resumeUserEvents
|
|
security:
|
|
- browserSession: []
|
|
- nativeBearer: []
|
|
parameters:
|
|
- name: version
|
|
in: query
|
|
required: false
|
|
schema: {type: string, enum: ['1']}
|
|
- name: cursor
|
|
in: query
|
|
required: false
|
|
schema: {type: string, maxLength: 512}
|
|
- name: Upgrade
|
|
in: header
|
|
required: false
|
|
schema: {type: string, enum: [websocket]}
|
|
- name: Sec-WebSocket-Version
|
|
in: header
|
|
required: false
|
|
schema: {type: string, enum: ['13']}
|
|
responses:
|
|
'200':
|
|
description: Bounded resumable NDJSON event snapshot; WebSocket upgrades emit the same envelopes as text frames.
|
|
headers:
|
|
X-VerseVDI-Event-Cursor:
|
|
schema: {type: string, maxLength: 512}
|
|
content:
|
|
application/x-ndjson:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/EventEnvelope
|
|
'400': {$ref: '#/components/responses/InvalidRequest'}
|
|
'401': {$ref: '#/components/responses/Unauthorized'}
|
|
'409': {$ref: '#/components/responses/Conflict'}
|
|
'426': {description: WebSocket version 13 is required.}
|
|
'503': {$ref: '#/components/responses/Unavailable'}
|
|
components:
|
|
securitySchemes:
|
|
browserSession:
|
|
type: apiKey
|
|
in: cookie
|
|
name: versevdi_session
|
|
browserCsrfCookie:
|
|
type: apiKey
|
|
in: cookie
|
|
name: versevdi_csrf
|
|
description: Must be identical to X-CSRF-Token and is checked against Server session state.
|
|
browserCsrfHeader:
|
|
type: apiKey
|
|
in: header
|
|
name: X-CSRF-Token
|
|
description: Must be identical to the versevdi_csrf cookie and is checked against Server session state.
|
|
nativeBearer:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: opaque
|
|
gatewayMutualTLS:
|
|
type: mutualTLS
|
|
parameters:
|
|
DeviceID:
|
|
name: device_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
SessionID:
|
|
name: session_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
AssignmentID:
|
|
name: assignment_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
PoolID:
|
|
name: pool_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
EntitlementID:
|
|
name: entitlement_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 128}
|
|
OperationID:
|
|
name: operation_id
|
|
in: path
|
|
required: true
|
|
schema: {type: string, format: uuid, pattern: '^(?!00000000-0000-0000-0000-000000000000$)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'}
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
required: false
|
|
schema: {type: integer, minimum: 1, maximum: 100, default: 100}
|
|
Cursor:
|
|
name: cursor
|
|
in: query
|
|
required: false
|
|
schema: {type: string, maxLength: 512}
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema: {type: string, minLength: 1, maxLength: 256}
|
|
responses:
|
|
InvalidRequest:
|
|
description: The request is invalid.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|
|
Unauthorized:
|
|
description: Authentication or credential validation failed without revealing credential state.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|
|
Forbidden:
|
|
description: The authenticated subject is not entitled to the requested action.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|
|
NotFound:
|
|
description: The resource is unavailable to this subject.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|
|
Conflict:
|
|
description: The expected version, protocol version, idempotency, or event retention boundary conflicts.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|
|
Unavailable:
|
|
description: The authoritative service is temporarily unavailable.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: ../schemas/control-v1.schema.json#/$defs/ErrorEnvelope
|