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 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 '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/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 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} 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