diff --git a/.gitignore b/.gitignore index e403a8a..45fc044 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ users.sqlite users.sqlite-shm users.sqlite-wal .env + +.npm-cache/ +.playwright-browsers/ +playwright-report/ +test-results/ +*.backup diff --git a/package.json b/package.json index 861f7bb..615e3ef 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,11 @@ "start": "node gambling.js", "dev": "node --watch gambling.js", "docs": "node swagger.js", - "check": "node --check gambling.js && node --check lib/poker.js && node --check public/frontend_home.js && node --check public/frontend_login.js && node --check public/frontend_poker.js && node --check public/matrix.js && node --check swagger.js", - "test": "npm run check && node --test" + "check": "node scripts/check.js && node swagger.js --check", + "test": "npm run check && node --test --test-isolation=none test/*.test.js", + "test:e2e": "playwright test", + "migrate:legacy": "node scripts/migrate-legacy.js", + "audit:deps": "npm audit --audit-level=high" }, "repository": { "type": "git", @@ -28,5 +31,8 @@ }, "devDependencies": { "@playwright/test": "^1.63.0" + }, + "engines": { + "node": ">=24" } } diff --git a/swagger.js b/swagger.js index 3e474b6..a764f76 100644 --- a/swagger.js +++ b/swagger.js @@ -1,25 +1,57 @@ -const swaggerAutogen = require('swagger-autogen')({openapi: '3.0.0'}); - -const doc = { - info: { - title: 'GAMBLE!', - description: 'Gambling API' - }, - servers: [{url: '/'}], - components: { - securitySchemes:{ - bearerAuth: { - type: 'http', - scheme: 'bearer' - } - } - } +const fs = require('node:fs'); +const {schemas} = require('./public/protocol'); +const object = (properties, required = Object.keys(properties)) => ({type: 'object', properties, required, additionalProperties: false}); +const string = {type: 'string'}; +const integer = {type: 'integer', minimum: 0, maximum: Number.MAX_SAFE_INTEGER}; +const nullableString = {type: ['string', 'null']}; +const numberMap = {type: 'object', additionalProperties: integer}; +const array = items => ({type: 'array', items}); +const user = object({username: string, money: integer}); +const error = object({code: string, error: string}); +const security = [{bearerAuth: []}, {cookieAuth: []}]; +const response = schema => ({description: 'Success', content: {'application/json': {schema}}}); +const responses = schema => ({200: response(schema), ...Object.fromEntries([400,401,403,404,409,429,500].map(status => [status, {description: `Error ${status}`, content: {'application/json': {schema: error}}}]))}); +const paths = {}; +function route(path, method, summary, output, body, auth = true) { + const entry = {summary, responses: responses(output), ...(auth ? {security} : {}), ...(body ? {requestBody: {required: true, content: {'application/json': {schema: body}}}} : {})}; + paths[path] ||= {}; paths[path][method] = entry; return entry; +} +const session = object({username: string, token: string}); +route('/register','post','Create a 200-chip account and session',session,schemas.credentials,false); +route('/login','post','Replace the current session',session,schemas.credentials,false); +route('/verify','post','Verify a cookie or bearer session',object({valid:{const:true},user:object({username:string,exp:integer})})); +route('/logout','delete','Fold/leave the lobby, revoke the session, and clear the cookie',object({message:string})); +route('/balance','get','Current spendable chips (excludes escrow)',object({balance:integer})); +route('/leaderboard','get','Rank spendable balances; username breaks ties',object({leaderboard:array(user),self:object({username:string,money:integer,position:integer})})); +const ack = object({lobbyId:string,username:string,type:string,requestId:string}); +for (const [path,type] of [['/lobby/create','lobby:create'],['/lobby/join','lobby:join'],['/lobby/leave','lobby:leave'],['/poker/start','poker:start'],['/poker/action','poker:action']]) { + const body = structuredClone(schemas[type]); delete body.properties.type; body.required = body.required.filter(key => key !== 'type'); + route(path,'post',`${type}; retry the identical body/requestId after a lost response`,ack,body); + paths[path].get = {summary:'Deprecated mutation method',responses:{405:{description:'Use POST',content:{'application/json':{schema:error}}}}}; +} +route('/lobby/public','get','List public lobbies',object({lobbies:array(object({lobbyId:string,host:nullableString,players:integer,gameStarted:{type:'boolean'}}))})); +route('/lobby/players','get','List members of your lobby',object({players:array(string)})).parameters=[{in:'query',name:'lobbyId',required:true,schema:schemas['lobby:join'].properties.lobbyId}]; +const doc = {openapi:'3.1.0',info:{title:'Gambling API',version:'2.0.0',description:'Virtual chips. Account balances exclude active-hand escrow. See docs/PROTOCOL.md and docs/RULES.md.'},servers:[{url:'/'}],paths, + components:{securitySchemes:{bearerAuth:{type:'http',scheme:'bearer',bearerFormat:'JWT'},cookieAuth:{type:'apiKey',in:'cookie',name:'authorization'}}}}; +const card = object({rank:{enum:['A','K','Q','J','10','9','8','7','6','5','4','3','2']},suit:{enum:['S','H','D','C']}}); +const result = object({rank:integer,name:string,score:array(integer),comboCards:array(card)}); +const outputSchemas = { + 'auth:success':object({type:{const:'auth:success'},username:string}), + 'command:ack':object({type:{const:'command:ack'},commandType:string,lobbyId:string,username:string,requestId:string}), + error:object({type:{const:'error'},code:string,message:string,requestId:string},['type','code','message']), + 'lobby:left':object({type:{const:'lobby:left'},lobbyId:string}), + 'lobby:state':object({type:{const:'lobby:state'},lobbyId:string,host:nullableString,players:array(string),isPublic:{type:'boolean'},canStart:{type:'boolean'},gameStarted:{type:'boolean'},gameUrl:string}), + 'poker:state':object({type:{const:'poker:state'},lobbyId:string,username:string,players:array(string),round:integer,pot:integer,currentBet:integer,bet:integer, + communityCards:array(card),hand:array(card),currentPlayer:nullableString,isYourTurn:{type:'boolean'},queue:array(string),folded:{type:'object',additionalProperties:{type:'boolean'}}, + street:{enum:['intermission','preflop','flop','turn','river']},phase:{enum:['intermission','waiting','betting']},lastAction:string,yourContribution:integer,yourStack:integer, + isSpectator:{type:'boolean'},callAmount:integer,minimumStake:integer,minimumRaise:integer,canRaise:{type:'boolean'}, + nextRoundStartsAt:{type:['integer','null']},turnEndsAt:{type:['integer','null']},winner:nullableString, + showdown:{anyOf:[{type:'null'},array(object({player:string,hand:array(card),result}))]},payouts:numberMap}) }; - -const outputFile = './swagger.json'; -const routes = ['./gambling.js']; - -/* NOTE: If you are using the express Router, you must pass in the 'routes' only the -root file where the route starts, such as index.js, app.js, routes.js, etc ... */ - -swaggerAutogen(outputFile, routes, doc); +const websocket = {$schema:'https://json-schema.org/draft/2020-12/schema',title:'WebSocket protocol',oneOf:Object.entries(schemas).filter(([key])=>key!=='credentials').map(([,value])=>value),$defs:outputSchemas}; +const artifacts = [['swagger.json',doc],['docs/websocket.schema.json',websocket]]; +for (const [filename, data] of artifacts) { + const text = JSON.stringify(data,null,2)+'\n'; + if (process.argv.includes('--check')) {if (fs.readFileSync(filename,'utf8') !== text) throw new Error(`${filename} is stale; run npm run docs`);} + else fs.writeFileSync(filename,text); +} diff --git a/swagger.json b/swagger.json index faa869e..0a689c6 100644 --- a/swagger.json +++ b/swagger.json @@ -1,9 +1,9 @@ { - "openapi": "3.0.0", + "openapi": "3.1.0", "info": { - "title": "GAMBLE!", - "description": "Gambling API", - "version": "1.0.0" + "title": "Gambling API", + "version": "2.0.0", + "description": "Virtual chips. Account balances exclude active-hand escrow. See docs/PROTOCOL.md and docs/RULES.md." }, "servers": [ { @@ -13,246 +13,1537 @@ "paths": { "/register": { "post": { - "description": "", + "summary": "Create a 200-chip account and session", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "required": [ + "username", + "token" + ], + "additionalProperties": false + } + } + } }, "400": { - "description": "Bad Request" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "username": { - "example": "any" + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } }, - "password": { - "example": "any" - } + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false } } } } - } - } - }, - "/leaderboard": { - "get": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "username", + "password" + ], + "properties": { + "username": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[^\\u0000-\\u001f\\u007f]+$" + }, + "password": { + "type": "string", + "minLength": 1, + "maxLength": 72 + } + }, + "additionalProperties": false + } } } - ], - "responses": { - "200": { - "description": "OK" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - } - }, - "security": [ - { - "bearerAuth": [] - } - ] + } } }, "/login": { - "get": { - "description": "", - "responses": { - "200": { - "description": "OK" - } - } - }, "post": { - "description": "", + "summary": "Replace the current session", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "required": [ + "username", + "token" + ], + "additionalProperties": false + } + } + } }, "400": { - "description": "Bad Request" + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" - } - }, - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "username": { - "example": "any" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } }, - "password": { - "example": "any" - } + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false } } } } - } - } - }, - "/": { - "get": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - } - } - } - }, - "/balance": { - "get": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not Found" - } }, - "security": [ - { - "bearerAuth": [] + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "username", + "password" + ], + "properties": { + "username": { + "type": "string", + "minLength": 1, + "maxLength": 40, + "pattern": "^[^\\u0000-\\u001f\\u007f]+$" + }, + "password": { + "type": "string", + "minLength": 1, + "maxLength": 72 + } + }, + "additionalProperties": false + } + } } - ] + } } }, "/verify": { "post": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], + "summary": "Verify a cookie or bearer session", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "valid": { + "const": true + }, + "user": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "exp": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + } + }, + "required": [ + "username", + "exp" + ], + "additionalProperties": false + } + }, + "required": [ + "valid", + "user" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "403": { - "description": "Forbidden" + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, "security": [ { "bearerAuth": [] + }, + { + "cookieAuth": [] } ] } }, "/logout": { "delete": { - "description": "", - "parameters": [ - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], + "summary": "Fold/leave the lobby, revoke the session, and clear the cookie", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + }, + "required": [ + "message" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "403": { - "description": "Forbidden" + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "404": { - "description": "Not Found" + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, "security": [ { "bearerAuth": [] + }, + { + "cookieAuth": [] } ] } }, - "/leave-lobby": { - "post": { - "description": "", + "/balance": { + "get": { + "summary": "Current spendable chips (excludes escrow)", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "balance": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + } + }, + "required": [ + "balance" + ], + "additionalProperties": false + } + } + } }, "400": { - "description": "Bad Request" + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "404": { - "description": "Not Found" + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ] + } + }, + "/leaderboard": { + "get": { + "summary": "Rank spendable balances; username breaks ties", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "leaderboard": { + "type": "array", + "items": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "money": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + } + }, + "required": [ + "username", + "money" + ], + "additionalProperties": false + } + }, + "self": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "money": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "position": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + } + }, + "required": [ + "username", + "money", + "position" + ], + "additionalProperties": false + } + }, + "required": [ + "leaderboard", + "self" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ] + } + }, + "/lobby/create": { + "post": { + "summary": "lobby:create; retry the identical body/requestId after a lost response", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "type": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "required": [ + "lobbyId", + "username", + "type", + "requestId" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ], "requestBody": { + "required": true, "content": { "application/json": { "schema": { "type": "object", + "required": [ + "requestId" + ], "properties": { - "lobbyId": { - "example": "any" + "requestId": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]{8,128}$" }, - "username": { - "example": "any" + "private": { + "type": "boolean" } + }, + "additionalProperties": false + } + } + } + } + }, + "get": { + "summary": "Deprecated mutation method", + "responses": { + "405": { + "description": "Use POST", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false } } } @@ -260,173 +1551,1494 @@ } } }, - "/lobby/create": { - "get": { - "description": "", - "parameters": [ - { - "name": "username", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], - "responses": { - "400": { - "description": "Bad Request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - } - }, - "security": [ - { - "bearerAuth": [] - } - ] - } - }, "/lobby/join": { - "get": { - "description": "", - "parameters": [ - { - "name": "lobbyId", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "username", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], + "post": { + "summary": "lobby:join; retry the identical body/requestId after a lost response", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "type": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "required": [ + "lobbyId", + "username", + "type", + "requestId" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "403": { - "description": "Forbidden" + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "404": { - "description": "Not Found" + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, "security": [ { "bearerAuth": [] + }, + { + "cookieAuth": [] } - ] + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "lobbyId", + "requestId" + ], + "properties": { + "lobbyId": { + "type": "string", + "pattern": "^[a-f0-9]{16}$" + }, + "requestId": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]{8,128}$" + } + }, + "additionalProperties": false + } + } + } + } + }, + "get": { + "summary": "Deprecated mutation method", + "responses": { + "405": { + "description": "Use POST", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + } } }, "/lobby/leave": { - "delete": { - "description": "", - "parameters": [ - { - "name": "lobbyId", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "username", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], + "post": { + "summary": "lobby:leave; retry the identical body/requestId after a lost response", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "type": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "required": [ + "lobbyId", + "username", + "type", + "requestId" + ], + "additionalProperties": false + } + } + } }, "400": { - "description": "Bad Request" + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "403": { - "description": "Forbidden" + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "404": { - "description": "Not Found" + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, "security": [ { "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "lobbyId", + "requestId" + ], + "properties": { + "lobbyId": { + "type": "string", + "pattern": "^[a-f0-9]{16}$" + }, + "requestId": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]{8,128}$" + } + }, + "additionalProperties": false + } + } + } + } + }, + "get": { + "summary": "Deprecated mutation method", + "responses": { + "405": { + "description": "Use POST", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + } + } + }, + "/poker/start": { + "post": { + "summary": "poker:start; retry the identical body/requestId after a lost response", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "type": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "required": [ + "lobbyId", + "username", + "type", + "requestId" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "lobbyId", + "requestId" + ], + "properties": { + "lobbyId": { + "type": "string", + "pattern": "^[a-f0-9]{16}$" + }, + "requestId": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]{8,128}$" + } + }, + "additionalProperties": false + } + } + } + } + }, + "get": { + "summary": "Deprecated mutation method", + "responses": { + "405": { + "description": "Use POST", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + } + } + }, + "/poker/action": { + "post": { + "summary": "poker:action; retry the identical body/requestId after a lost response", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "username": { + "type": "string" + }, + "type": { + "type": "string" + }, + "requestId": { + "type": "string" + } + }, + "required": [ + "lobbyId", + "username", + "type", + "requestId" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "lobbyId", + "requestId", + "action" + ], + "properties": { + "lobbyId": { + "type": "string", + "pattern": "^[a-f0-9]{16}$" + }, + "requestId": { + "type": "string", + "pattern": "^[a-zA-Z0-9_-]{8,128}$" + }, + "action": { + "enum": [ + "hit", + "fold", + "bet" + ] + }, + "payload": { + "type": "object", + "properties": { + "amount": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false + } + } + } + } + }, + "get": { + "summary": "Deprecated mutation method", + "responses": { + "405": { + "description": "Use POST", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + } + } + }, + "/lobby/public": { + "get": { + "summary": "List public lobbies", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "lobbies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "lobbyId": { + "type": "string" + }, + "host": { + "type": [ + "string", + "null" + ] + }, + "players": { + "type": "integer", + "minimum": 0, + "maximum": 9007199254740991 + }, + "gameStarted": { + "type": "boolean" + } + }, + "required": [ + "lobbyId", + "host", + "players", + "gameStarted" + ], + "additionalProperties": false + } + } + }, + "required": [ + "lobbies" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "401": { + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "403": { + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + } + }, + "security": [ + { + "bearerAuth": [] + }, + { + "cookieAuth": [] } ] } }, "/lobby/players": { "get": { - "description": "", - "parameters": [ - { - "name": "lobbyId", - "in": "query", - "schema": { - "type": "string" - } - }, - { - "name": "authorization", - "in": "header", - "schema": { - "type": "string" - } - } - ], + "summary": "List members of your lobby", "responses": { "200": { - "description": "OK" + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "players": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "players" + ], + "additionalProperties": false + } + } + } + }, + "400": { + "description": "Error 400", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "401": { - "description": "Unauthorized" + "description": "Error 401", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } }, "403": { - "description": "Forbidden" + "description": "Error 403", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "404": { + "description": "Error 404", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "409": { + "description": "Error 409", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "429": { + "description": "Error 429", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } + }, + "500": { + "description": "Error 500", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "error": { + "type": "string" + } + }, + "required": [ + "code", + "error" + ], + "additionalProperties": false + } + } + } } }, "security": [ { "bearerAuth": [] + }, + { + "cookieAuth": [] + } + ], + "parameters": [ + { + "in": "query", + "name": "lobbyId", + "required": true, + "schema": { + "type": "string", + "pattern": "^[a-f0-9]{16}$" + } } ] } @@ -436,7 +3048,13 @@ "securitySchemes": { "bearerAuth": { "type": "http", - "scheme": "bearer" + "scheme": "bearer", + "bearerFormat": "JWT" + }, + "cookieAuth": { + "type": "apiKey", + "in": "cookie", + "name": "authorization" } } }