feat(rust): identity — a link code from the game, and the Steam id inside core's user page
R1's identity link, site-side, and R13's first extension slot. A player types /link in game, the plugin hands them a six-character code privately, and they enter it here; the site records who owns which Steam account, and an operator sees that on core's own `/admin/users/:id` page. **The site is the author of record and the game holds nothing.** There is no per-account store in Rust that survives a wipe, and phase 7 needs the site authoritative anyway — it pushes permissions INTO the game keyed by Steam id. A copy in the game would be a second thing to reconcile every wipe, for no question it could answer better. ## D24 — a code is minted by ONE server, so every server is asked Nothing in six characters says where it came from. The fleet is asked in turn and the first `link.ok` wins; the others answer `unknown` and nothing happens there, because a code is only spent at the server that actually holds it. Asking the player to pick was rejected: a wrong pick would come back indistinguishable from a wrong code, and that is the one refusal which must not be ambiguous. **"Every reachable server refused" is not the same answer as "a server was unreachable."** Collapsing them tells a player whose server is down that their code is wrong — so they run /link again on that same server and are told the same thing for as long as it stays down. `unsure` is that case, and it says to try again rather than to fetch a new code. ## D23 — a Steam id another account holds is refused, never moved The primary key is `steam_id`, and it is load-bearing rather than tidy: phase 7 grants permissions against a link and phase 13 hangs entitlements off it, so a silent move is an account takeover performed by typing six characters. The refusal names the holder, because the advice is unusable without it. The INSERT is a plain INSERT for the same reason — `ON DUPLICATE KEY UPDATE` here would BE that move — and the duplicate-key error is the refusal for the race the check above cannot close. The way out is `/unlink` in game, which reaches the site off the ingest feed rather than through a route (the plugin has no link to delete). D25 adds the other way out: staff can sever a link from the admin panel, for a player who cannot reach that Steam account in game. ## The slot, and the hole it found in this repo's own generator `admin.users.detail` is declared in `module.json` AND registered in `index.js` AND filled by the chunk — three places, because the server half and the client half are different registrations that share one name. `swaggerFragment.js` knew only about tier routers, so the two routes under `/admin/users/:id` were generated by nothing: a fragment that was internally consistent and described two routes fewer than the module serves. A slot's mount is core's and cannot be derived here, so it is a fourth constant beside `TIER_BASE` — held to account by the frozen-manifest job, which was verified to catch exactly this by removing the two paths and watching it fail. ## Smaller things worth knowing - **Core's `useAsync` has no `refresh`.** A counter in the deps is how a page re-reads after its own write; it blanks while it re-reads, which is right here and is exactly what made it wrong for a poll. - **Every player-portal nav row needs an `icon`** — core draws one on every row, and the client suite says so. This module had no icons file until now, because the public header is text buttons. - The two new frame kinds are STAFF-only. Neither carries a code, but both name a Steam id beside a website account's activity, and that join is not a public fact about what happened on a server. - The link code route carries its own rate limiter rather than core's `accountChangeLimiter`: this is guessing somebody else's secret, not changing your own password, and a shared counter would let one policy set the other. Protocol 3 on all three declaration sites; 17 new tests, 136 green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMH6bw1jXMgbyF3ZWGEzSM
This commit is contained in:
@@ -148,6 +148,290 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/users/{id}/rust/links": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Admin · Users"
|
||||
],
|
||||
"summary": "A user’s linked Steam accounts and their Rust record (admin only)",
|
||||
"description": "Every Steam account linked to this website user, with the display name the game last saw and, per server, all-time kills / deaths / playtime across every wipe. Fills the admin.users.detail extension slot.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "User id."
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Linked accounts",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RustAdminLinkList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"cookieAuth": []
|
||||
},
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/users/{id}/rust/links/{steamId}": {
|
||||
"delete": {
|
||||
"tags": [
|
||||
"Admin · Users"
|
||||
],
|
||||
"summary": "Sever a user’s Steam link (admin only)",
|
||||
"description": "Staff release a link on this user’s behalf. It is the counterweight to the site refusing to move a Steam id another account holds: a player who cannot reach that Steam account in game has no other way back. Recorded in the activity log.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "User id."
|
||||
},
|
||||
{
|
||||
"name": "steamId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The Steam id to release."
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Unlinked",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"unlinked": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not linked to this user",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"cookieAuth": []
|
||||
},
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/player/rust/link": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Player · Rust"
|
||||
],
|
||||
"summary": "Link a Steam account with a one-time code from /link in game",
|
||||
"description": "The player types /link in game, the plugin hands them a six-character code privately, and they enter it here within five minutes. The site asks each configured server in turn until one recognises the code. A Steam account already linked to a different website account is refused rather than moved — the way out is /unlink in game.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Linked",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RustLinkResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Unknown or expired code",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "That Steam account is linked to another website account",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "Too many link attempts",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
},
|
||||
"503": {
|
||||
"description": "A server could not be reached — the code is still good",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"cookieAuth": []
|
||||
},
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RustLinkRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/player/rust/links": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Player · Rust"
|
||||
],
|
||||
"summary": "The Steam accounts the caller has linked",
|
||||
"description": "Every Steam account linked to the signed-in user, newest first. A link is fleet-wide: it is keyed by Steam id, not by server, because a Steam account is one person across every server an operator runs.",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Linked accounts",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/RustLinkList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"cookieAuth": []
|
||||
},
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/player/rust/links/{steamId}": {
|
||||
"delete": {
|
||||
"tags": [
|
||||
"Player · Rust"
|
||||
],
|
||||
"summary": "Release a Steam account the caller has linked",
|
||||
"description": "Removes the caller’s own link. Scoped to the caller in the statement, so a link belonging to somebody else answers the same 404 as one that does not exist.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "steamId",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "The Steam id to release."
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Unlinked",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"unlinked": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not linked to the caller",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"cookieAuth": []
|
||||
},
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/player/rust/servers": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -854,6 +1138,517 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustLink": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "One Steam account linked to a website user. Never carries a code."
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"steamId": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "76561198000000000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "What the player was called in game when they linked. A display name only — a Rust name changes on a whim and nothing identifies anybody by it."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "Wanderer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serverId": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "Which server minted the code. Not part of the identity — a link is fleet-wide — but it is where a support conversation starts."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "main"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linkedAt": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"example": "date-time"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustLinkList": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "The Steam accounts one website user holds (GET /player/rust/links)."
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/RustLink"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustLinkRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"required": {
|
||||
"type": "array",
|
||||
"example": [
|
||||
"code"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "The six-character code /link handed the player in game. Good for five minutes, and it works once."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "K7M2PQ"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustLinkResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "The result of redeeming a code."
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"linked": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "boolean"
|
||||
},
|
||||
"example": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"$ref": "#/components/schemas/RustLink"
|
||||
},
|
||||
"already": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "boolean"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "True when this Steam id was already linked to the caller — a second press of the button, not an error."
|
||||
},
|
||||
"example": {
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustAdminLinkList": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "One user’s Rust identity, for the admin.users.detail panel (GET /admin/users/{id}/rust/links)."
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"steamId": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "76561198000000000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "What the game last saw this player called, falling back to the name recorded at link time."
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "Wanderer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linkedName": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "Wanderer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serverId": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "main"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linkedAt": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"example": "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"firstSeen": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"example": "date-time"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"lastSeen": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"example": "date-time"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"servers": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "array"
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"example": "All-time totals per server, summed across every wipe."
|
||||
},
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "object"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"serverId": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "main"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serverName": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"example": {
|
||||
"type": "string",
|
||||
"example": "Main · Vanilla"
|
||||
}
|
||||
}
|
||||
},
|
||||
"kills": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 41
|
||||
}
|
||||
}
|
||||
},
|
||||
"deaths": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 37
|
||||
}
|
||||
}
|
||||
},
|
||||
"npcKills": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 120
|
||||
}
|
||||
}
|
||||
},
|
||||
"structures": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 64
|
||||
}
|
||||
}
|
||||
},
|
||||
"playtimeSec": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 43200
|
||||
}
|
||||
}
|
||||
},
|
||||
"wipes": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "integer"
|
||||
},
|
||||
"example": {
|
||||
"type": "number",
|
||||
"example": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"lastSeen": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"example": "string"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"example": "date-time"
|
||||
},
|
||||
"nullable": {
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RustSidecarProbe": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Reference in New Issue
Block a user