// ── The OpenAPI fragment: the shared half ───────────────────────────────── // // The tags and component schemas the `#swagger.*` annotations refer to. // `scripts/swaggerFragment.js` feeds this to swagger-autogen; the per-endpoint // detail lives beside each route, exactly as it does in core. // // **Two rules about names, and both belong to the MERGED document rather than to // this file** (MODULE_API.md §6.1a). Core merges every started module's fragment // over its own committed spec and serves the result at `/api/docs.json`, and core // wins any key collision: // // • **Namespace what you DEFINE.** `RustServerList`, not `ServerList`. A second // game's module describing the same idea under the same bare name would // silently clobber this one or be clobbered by it. // • **Reference what CORE defines by core's name.** `#/components/schemas/Error` // and `ValidationError` are core's; point at them and do not redefine them. // // **swagger-autogen renders `components.schemas` from an EXAMPLE object, not from // raw OpenAPI.** `{ type: 'object' }` comes back as a meta-description of itself. // That is uniform across core's committed spec and is the house shape. module.exports = { tags: [ { name: 'Public · Rust', description: 'The Rust servers this site follows, as each one last reported itself', }, { name: 'Player · Rust', description: 'The Rust surface for a signed-in player', }, { name: 'Admin · Rust', description: 'Configuring the Rust servers and their sidecars', }, ], components: { schemas: { RustServerList: { type: 'object', description: 'Every Rust server this site follows (GET /public/rust/servers).', properties: { servers: { type: 'array', items: { $ref: '#/components/schemas/RustServer' }, }, }, }, RustServer: { type: 'object', description: 'One Rust server, as it last reported itself.', properties: { id: { type: 'string', example: 'main' }, name: { type: 'string', example: 'Main · Vanilla' }, online: { type: 'boolean', example: true }, players: { type: 'integer', example: 42 }, maxPlayers: { type: 'integer', example: 100 }, hostname: { type: 'string', nullable: true, example: 'Runic Gateway · Main' }, level: { type: 'string', nullable: true, example: 'Procedural Map' }, worldSize: { type: 'integer', nullable: true, example: 4000 }, seed: { type: 'integer', nullable: true, example: 1234 }, updatedAt: { type: 'string', format: 'date-time', nullable: true }, stale: { type: 'boolean', description: 'Has nothing reported in longer than the freshness window? A stale row is reported offline.', example: false, }, }, }, RustAdminServerList: { type: 'object', description: 'The configured servers, with their sidecar settings (GET /admin/rust/servers).', properties: { servers: { type: 'array', items: { $ref: '#/components/schemas/RustAdminServer' }, }, }, }, RustAdminServer: { type: 'object', description: 'One configured server. The sidecar token is never included — `hasToken` reports only whether one is stored.', properties: { id: { type: 'string', example: 'main' }, name: { type: 'string', example: 'Main · Vanilla' }, sidecarBaseUrl: { type: 'string', example: 'http://10.0.0.5:8090' }, hasToken: { type: 'boolean', example: true }, protocol: { type: 'integer', example: 1 }, enabled: { type: 'boolean', example: true }, sortOrder: { type: 'integer', example: 0 }, reachable: { type: 'boolean', description: 'Did the sidecar answer on the last poll? Separate from `online`, which is about the game rather than the bridge.', example: true, }, bootId: { type: 'string', nullable: true, example: 'boot-20260915T194502Z' }, sidecarProtocol: { type: 'integer', nullable: true, example: 1 }, online: { type: 'boolean', example: true }, players: { type: 'integer', example: 42 }, stale: { type: 'boolean', example: false }, }, }, RustSidecarProbe: { type: 'object', description: 'What a sidecar said when probed (POST /admin/rust/servers/{id}/test).', properties: { ok: { type: 'boolean', example: true }, status: { type: 'string', description: 'What happened, in one word — this is what tells a wrong URL from a wrong token from a mismatched protocol. One of `ok`, `no-token`, `unauthorized`, `protocol-mismatch`, `timeout`, `transport-error`, or `http-`.', example: 'ok', }, sidecar: { type: 'object', nullable: true, description: 'The sidecar’s own health document, or the mismatch detail on a protocol disagreement.', properties: { status: { type: 'string', example: 'ok' }, protocol: { type: 'integer', example: 1 }, plugin_connected: { type: 'boolean', example: true }, database: { type: 'string', example: 'ok' }, uptime: { type: 'string', example: '3h 2m' }, last_event: { type: 'string', format: 'date-time', nullable: true }, }, }, }, }, }, }, }