{
  "openapi": "3.1.1",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Manak — submission and judging",
    "version": "0.1.0",
    "description": "Every operation is dispatched at two paths: JSON under /api, and the same path without the prefix for a browser. A read renders a page there; a write accepts a form there and answers with a redirect to the page that shows its result. There is no operation on one surface that is missing from the other."
  },
  "tags": [
    {
      "name": "system"
    },
    {
      "name": "auth"
    },
    {
      "name": "tokens"
    },
    {
      "name": "events"
    },
    {
      "name": "comments"
    },
    {
      "name": "tracks"
    },
    {
      "name": "teams"
    },
    {
      "name": "projects"
    },
    {
      "name": "duplicates"
    },
    {
      "name": "rubrics"
    },
    {
      "name": "judging"
    },
    {
      "name": "ballots"
    },
    {
      "name": "duels"
    },
    {
      "name": "assignments"
    },
    {
      "name": "judges"
    },
    {
      "name": "reviews"
    },
    {
      "name": "results"
    },
    {
      "name": "awards"
    },
    {
      "name": "appeals"
    },
    {
      "name": "votes"
    },
    {
      "name": "exports"
    }
  ],
  "paths": {
    "/api": {
      "get": {
        "operationId": "system_home",
        "summary": "List the events this deployment is running.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List the events this deployment is running.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product": {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string"
                        },
                        "version": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "author": {
                          "type": "string"
                        },
                        "source": {
                          "type": "string",
                          "format": "uri"
                        },
                        "license": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "title",
                        "version",
                        "tagline",
                        "author",
                        "source",
                        "license"
                      ]
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "timezone": {
                            "type": "string"
                          },
                          "prizes": {
                            "type": "string"
                          },
                          "questions": {
                            "type": "string"
                          },
                          "phase": {
                            "type": "string",
                            "enum": [
                              "upcoming",
                              "submissions",
                              "overlap",
                              "judging",
                              "between",
                              "finished"
                            ]
                          },
                          "submissionsOpen": {
                            "type": "boolean"
                          },
                          "judgingOpen": {
                            "type": "boolean"
                          },
                          "resultsPublic": {
                            "type": "boolean"
                          },
                          "archived": {
                            "type": "boolean"
                          },
                          "votingMode": {
                            "type": "string",
                            "enum": [
                              "off",
                              "open",
                              "account"
                            ]
                          },
                          "votingOpenAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "votingCloseAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "votingCredits": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "name",
                          "phase",
                          "votingMode",
                          "votingOpenAt",
                          "votingCloseAt",
                          "votingCredits"
                        ]
                      }
                    }
                  },
                  "required": [
                    "product",
                    "events"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.home",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/about": {
      "get": {
        "operationId": "system_about",
        "summary": "Describe what this deployment is and who wrote it.",
        "description": "Callable by anyone, signed in or not.\n\nEvery claim below names the route or the file that settles it. Nothing on this page is measured at request time, so two deployments of the same version answer identically.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Describe what this deployment is and who wrote it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product": {
                      "type": "object",
                      "properties": {
                        "title": {
                          "type": "string"
                        },
                        "version": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "author": {
                          "type": "string"
                        },
                        "source": {
                          "type": "string",
                          "format": "uri"
                        },
                        "license": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "title",
                        "version",
                        "tagline",
                        "author",
                        "source",
                        "license"
                      ]
                    },
                    "built": {
                      "type": "object",
                      "description": "How this deployment is assembled, counted from what is running.",
                      "properties": {
                        "dependencies": {
                          "type": "integer"
                        },
                        "operations": {
                          "type": "integer"
                        },
                        "runtime": {
                          "type": "string"
                        },
                        "storage": {
                          "type": "string"
                        },
                        "clientScript": {
                          "type": "boolean"
                        }
                      }
                    },
                    "claims": {
                      "type": "array",
                      "description": "Each claim this project makes, with where to check it.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "claim": {
                            "type": "string"
                          },
                          "check": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "claim",
                          "check"
                        ]
                      }
                    }
                  },
                  "required": [
                    "product",
                    "built",
                    "claims"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.about",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/docs": {
      "get": {
        "operationId": "system_docs",
        "summary": "Describe every operation this deployment performs.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Describe every operation this deployment performs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "operations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "method": {
                            "type": "string",
                            "enum": [
                              "GET",
                              "POST"
                            ]
                          },
                          "path": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "callableBy": {
                            "type": "string"
                          },
                          "records": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "where": {
                                  "type": "string",
                                  "enum": [
                                    "path",
                                    "query",
                                    "body"
                                  ]
                                },
                                "meaning": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "operations"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.docs",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "system_openapi",
        "summary": "Publish the OpenAPI description of this deployment.",
        "description": "Callable by anyone, signed in or not.\n\nThe document is derived from the same command declarations the server dispatches, so a generated client is generated against what is actually running.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Publish the OpenAPI description of this deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "An OpenAPI 3.1 document."
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.openapi",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/capabilities": {
      "get": {
        "operationId": "system_capabilities",
        "summary": "Publish the access matrix for every operation.",
        "description": "Callable by anyone, signed in or not.\n\n`stranger` is a signed-in account with no role in the event, which is also how an organizer of a different event presents itself. A `notFound` cell is the isolation rule: not yours means not found, never forbidden.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Publish the access matrix for every operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "witnesses": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "route": {
                            "type": "string"
                          },
                          "audience": {
                            "type": "string"
                          },
                          "owner": {
                            "type": "string"
                          },
                          "gate": {
                            "type": "string"
                          },
                          "cells": {
                            "type": "object",
                            "description": "Per witness: allow, unauthenticated, forbidden or notFound.",
                            "additionalProperties": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "witnesses",
                    "rows"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.capabilities",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/healthz": {
      "get": {
        "operationId": "system_healthz",
        "summary": "Report whether this deployment is serving correctly.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Report whether this deployment is serving correctly.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ]
                    },
                    "at": {
                      "type": "integer",
                      "description": "Server time, epoch milliseconds."
                    },
                    "version": {
                      "type": "string"
                    },
                    "migrations": {
                      "type": "object",
                      "properties": {
                        "current": {
                          "type": "boolean"
                        },
                        "applied": {
                          "type": "integer"
                        },
                        "pending": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "ledger": {
                      "type": "object",
                      "description": "The audit chain's length and head hash. The hash is safe to publish.",
                      "properties": {
                        "length": {
                          "type": "integer"
                        },
                        "headHash": {
                          "type": "string"
                        }
                      }
                    },
                    "problems": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "status",
                    "at",
                    "version",
                    "ledger"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.healthz",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/system/limits": {
      "get": {
        "operationId": "system_limits",
        "summary": "List fixed-window rate limiting policies and status 429 contract.",
        "description": "Callable by anyone, signed in or not.\n\nPublic policy specification. Explains fixed-window rate meters and Retry-After header semantics.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List fixed-window rate limiting policies and status 429 contract.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "limits": {
                      "type": "object"
                    },
                    "status429Contract": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "limits",
                    "status429Contract"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.limits",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/system/rate-probe": {
      "post": {
        "operationId": "system_rate_probe",
        "summary": "Safe rate limit probe endpoint to exercise 429 flood refusal.",
        "description": "Callable by anyone, signed in or not.\n\nEnforces 2 requests per minute. Exceeding triggers HTTP 429 Too Many Requests with Retry-After header.",
        "tags": [
          "system"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Safe rate limit probe endpoint to exercise 429 flood refusal.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string"
                    },
                    "window": {
                      "type": "string"
                    },
                    "max": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "ok",
                    "status",
                    "window",
                    "max"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "system.rate_probe",
        "x-manak-capability": {
          "audience": "public"
        },
        "x-manak-records": [
          "system.probed"
        ],
        "x-manak-limit": "probe"
      }
    },
    "/api/signin": {
      "get": {
        "operationId": "auth_signin",
        "summary": "Show how to sign in.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "auth"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "sent",
            "in": "query",
            "required": false,
            "description": "Set by the redirect after a link has been requested. Nothing reads it but the page.",
            "schema": {
              "description": "Set by the redirect after a link has been requested. Nothing reads it but the page.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show how to sign in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request": {
                      "type": "string",
                      "description": "The operation that sends a link."
                    },
                    "route": {
                      "type": "string"
                    },
                    "field": {
                      "type": "string"
                    },
                    "expiresInMinutes": {
                      "type": "integer"
                    },
                    "sent": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "request",
                    "route",
                    "field",
                    "expiresInMinutes"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.signin",
        "x-manak-capability": {
          "audience": "public"
        }
      },
      "post": {
        "operationId": "auth_request",
        "summary": "Send a sign-in link to an email address.",
        "description": "Callable by anyone, signed in or not.\n\nAnswers identically for a known and an unknown address, so this cannot be used to find out who has an account here.",
        "tags": [
          "auth"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "description": "Where to send the link. It is the address an organizer invited, if you were invited.",
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  }
                },
                "required": [
                  "email"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "description": "Where to send the link. It is the address an organizer invited, if you were invited.",
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  }
                },
                "required": [
                  "email"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Send a sign-in link to an email address.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sent": {
                      "type": "boolean",
                      "description": "Always true. It does not mean an account exists."
                    },
                    "expiresAt": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "sent",
                    "expiresAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.request",
        "x-manak-capability": {
          "audience": "public"
        },
        "x-manak-records": [
          "signin.requested"
        ],
        "x-manak-limit": "signin"
      }
    },
    "/api/signin/{token}": {
      "get": {
        "operationId": "auth_link",
        "summary": "Show the button that completes a sign-in.",
        "description": "Callable by anyone, signed in or not.\n\nDeliberately inert. It does not consume the link, so a scanner or prefetcher that opens the URL cannot spend it before the person does.",
        "tags": [
          "auth"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The token from the link that was sent to you.",
            "schema": {
              "description": "The token from the link that was sent to you.",
              "type": "string",
              "minLength": 43,
              "maxLength": 43
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show the button that completes a sign-in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "confirm": {
                      "type": "string",
                      "description": "The route that turns this token into a session."
                    },
                    "field": {
                      "type": "string"
                    },
                    "expiresInMinutes": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "confirm",
                    "field",
                    "expiresInMinutes"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.link",
        "x-manak-capability": {
          "audience": "public"
        }
      }
    },
    "/api/session": {
      "post": {
        "operationId": "auth_session",
        "summary": "Exchange a sign-in link for a session.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "auth"
        ],
        "security": [
          {}
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The token from the link that was sent to you.",
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 43
                  }
                },
                "required": [
                  "token"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The token from the link that was sent to you.",
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 43
                  }
                },
                "required": [
                  "token"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Exchange a sign-in link for a session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id",
                        "email",
                        "displayName"
                      ]
                    },
                    "token": {
                      "type": "string",
                      "description": "The session credential. Send it as `Authorization: Bearer <token>`. It is also set as a cookie, so a browser can ignore this field."
                    },
                    "expiresAt": {
                      "type": "integer"
                    },
                    "eventId": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The event this link was an invitation to, if it was one."
                    },
                    "role": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "organizer",
                        "judge",
                        "participant",
                        null
                      ]
                    }
                  },
                  "required": [
                    "account",
                    "token",
                    "expiresAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.session",
        "x-manak-capability": {
          "audience": "public"
        },
        "x-manak-records": [
          "link.consumed",
          "account.created",
          "membership.granted",
          "session.created"
        ],
        "x-manak-limit": "signin"
      }
    },
    "/api/whoami": {
      "get": {
        "operationId": "auth_whoami",
        "summary": "Describe the signed-in account and its live sessions.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Describe the signed-in account and its live sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        },
                        "displayName": {
                          "type": "string"
                        },
                        "createdAt": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "email",
                        "displayName",
                        "createdAt"
                      ]
                    },
                    "founder": {
                      "type": "boolean",
                      "description": "Whether this deployment's operator listed this address as a founder, which is what allows an event to be created. It is read from the environment, not stored."
                    },
                    "sessions": {
                      "type": "array",
                      "description": "Every session of this account that has not expired or been revoked.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "createdAt": {
                            "type": "integer"
                          },
                          "lastSeenAt": {
                            "type": "integer"
                          },
                          "expiresAt": {
                            "type": "integer"
                          },
                          "userAgent": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "account",
                    "sessions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.whoami",
        "x-manak-capability": {
          "audience": "account"
        }
      }
    },
    "/api/signout": {
      "post": {
        "operationId": "auth_signout",
        "summary": "Sign out of this session, or of every session.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "everywhere": {
                    "description": "Revoke every session for this account, not just this one. Use it if you think a link or a token has been seen by somebody else.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "everywhere": {
                    "description": "Revoke every session for this account, not just this one. Use it if you think a link or a token has been seen by somebody else.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sign out of this session, or of every session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signedOut": {
                      "type": "boolean"
                    },
                    "everywhere": {
                      "type": "boolean"
                    },
                    "remaining": {
                      "type": "integer",
                      "description": "Sessions still live for this account after the revocation."
                    }
                  },
                  "required": [
                    "signedOut",
                    "everywhere",
                    "remaining"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "auth.signout",
        "x-manak-capability": {
          "audience": "account"
        },
        "x-manak-records": [
          "session.revoked"
        ],
        "x-manak-limit": "read"
      }
    },
    "/api/me/tokens": {
      "get": {
        "operationId": "tokens_list",
        "summary": "Manage your scoped API tokens.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "tokens"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Manage your scoped API tokens.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tokens": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "tokens"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "tokens.list",
        "x-manak-capability": {
          "audience": "account"
        }
      },
      "post": {
        "operationId": "tokens_create",
        "summary": "Create an expiring API token for one event and scope.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "tokens"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "description": "The event's slug or id, as it appears in the URL.",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 64
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "read:projects",
                      "read:results",
                      "write:projects",
                      "write:judging"
                    ],
                    "default": "read:projects"
                  },
                  "days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "default": 30
                  }
                },
                "required": [
                  "event",
                  "label"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "description": "The event's slug or id, as it appears in the URL.",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 64
                  },
                  "label": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "read:projects",
                      "read:results",
                      "write:projects",
                      "write:judging"
                    ],
                    "default": "read:projects"
                  },
                  "days": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 90,
                    "default": 30
                  }
                },
                "required": [
                  "event",
                  "label"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Create an expiring API token for one event and scope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "expiresAt": {
                      "type": "integer"
                    },
                    "eventId": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "token",
                    "scope",
                    "expiresAt",
                    "eventId"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "tokens.create",
        "x-manak-capability": {
          "audience": "account",
          "scope": "event"
        },
        "x-manak-records": [
          "token.created"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/me/tokens/{tokenId}/revoke": {
      "post": {
        "operationId": "tokens_revoke",
        "summary": "Immediately revoke one of your API tokens.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "tokens"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "tokenId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Immediately revoke one of your API tokens.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "revoked"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "tokens.revoke",
        "x-manak-capability": {
          "audience": "account"
        },
        "x-manak-records": [
          "token.revoked"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events": {
      "get": {
        "operationId": "events_list",
        "summary": "List the events this deployment is running.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "events"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "archived",
            "in": "query",
            "required": false,
            "description": "Include events that have been archived. They stay reachable by slug either way.",
            "schema": {
              "description": "Include events that have been archived. They stay reachable by slug either way.",
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the events this deployment is running.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "timezone": {
                            "type": "string"
                          },
                          "prizes": {
                            "type": "string"
                          },
                          "questions": {
                            "type": "string"
                          },
                          "phase": {
                            "type": "string",
                            "enum": [
                              "upcoming",
                              "submissions",
                              "overlap",
                              "judging",
                              "between",
                              "finished"
                            ]
                          },
                          "submissionsOpen": {
                            "type": "boolean"
                          },
                          "judgingOpen": {
                            "type": "boolean"
                          },
                          "resultsPublic": {
                            "type": "boolean"
                          },
                          "archived": {
                            "type": "boolean"
                          },
                          "votingMode": {
                            "type": "string",
                            "enum": [
                              "off",
                              "open",
                              "account"
                            ]
                          },
                          "votingOpenAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "votingCloseAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "votingCredits": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "id",
                          "slug",
                          "name",
                          "phase",
                          "votingMode",
                          "votingOpenAt",
                          "votingCloseAt",
                          "votingCredits"
                        ]
                      }
                    }
                  },
                  "required": [
                    "events"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.list",
        "x-manak-capability": {
          "audience": "public"
        }
      },
      "post": {
        "operationId": "events_create",
        "summary": "Create an event and become its organizer.",
        "description": "Callable by an account this deployment's operator listed as a founder.\n\nLimited to the addresses this deployment's operator named as founders. Holding any role in an existing event, including organizer, does not grant it.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "description": "Lower-case letters, digits and hyphens. It appears in every link to this event and cannot be changed.",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 64
                  },
                  "name": {
                    "description": "What people call it. “Dogfood Hackathon 2026”, not “dogfood-2026”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "prizes": {
                    "description": "One prize per line, including its amount and eligibility.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "questions": {
                    "description": "One question per line. Teams answer these publicly on their project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "timezone": {
                    "description": "An IANA zone such as Europe/Lisbon, used for displaying times. Every deadline is still one instant for everybody.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "default": "UTC"
                  },
                  "submissionsOpenAt": {
                    "description": "When teams may start submitting.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "submissionsCloseAt": {
                    "description": "The deadline. It is enforced to the millisecond.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingOpenAt": {
                    "description": "When judges may start scoring. It may be before submissions close.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingCloseAt": {
                    "description": "When scoring stops.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "reviewsPerProject": {
                    "description": "How many judges should see each project. Three is the usual answer; below three there is nothing to cross-check a lenient judge against.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "default": 3
                  },
                  "pairwiseEnabled": {
                    "description": "Ask judges which of two projects is better, as well as scoring each. It sharpens the top of the leaderboard and costs judges time.",
                    "type": "boolean",
                    "default": false
                  },
                  "votingOpenAt": {
                    "description": "When community voting begins.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingCloseAt": {
                    "description": "When community voting ends.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingMode": {
                    "description": "Choose off, open to a voter token, or signed-in accounts only.",
                    "type": "string",
                    "enum": [
                      "off",
                      "open",
                      "account"
                    ],
                    "default": "off"
                  },
                  "votingCredits": {
                    "description": "The quadratic voting budget per voter.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000,
                    "default": 100
                  }
                },
                "required": [
                  "slug",
                  "name",
                  "submissionsOpenAt",
                  "submissionsCloseAt",
                  "judgingOpenAt",
                  "judgingCloseAt"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "description": "Lower-case letters, digits and hyphens. It appears in every link to this event and cannot be changed.",
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 64
                  },
                  "name": {
                    "description": "What people call it. “Dogfood Hackathon 2026”, not “dogfood-2026”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "prizes": {
                    "description": "One prize per line, including its amount and eligibility.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "questions": {
                    "description": "One question per line. Teams answer these publicly on their project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "timezone": {
                    "description": "An IANA zone such as Europe/Lisbon, used for displaying times. Every deadline is still one instant for everybody.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "default": "UTC"
                  },
                  "submissionsOpenAt": {
                    "description": "When teams may start submitting.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "submissionsCloseAt": {
                    "description": "The deadline. It is enforced to the millisecond.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingOpenAt": {
                    "description": "When judges may start scoring. It may be before submissions close.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingCloseAt": {
                    "description": "When scoring stops.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "reviewsPerProject": {
                    "description": "How many judges should see each project. Three is the usual answer; below three there is nothing to cross-check a lenient judge against.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "default": 3
                  },
                  "pairwiseEnabled": {
                    "description": "Ask judges which of two projects is better, as well as scoring each. It sharpens the top of the leaderboard and costs judges time.",
                    "type": "boolean",
                    "default": false
                  },
                  "votingOpenAt": {
                    "description": "When community voting begins.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingCloseAt": {
                    "description": "When community voting ends.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingMode": {
                    "description": "Choose off, open to a voter token, or signed-in accounts only.",
                    "type": "string",
                    "enum": [
                      "off",
                      "open",
                      "account"
                    ],
                    "default": "off"
                  },
                  "votingCredits": {
                    "description": "The quadratic voting budget per voter.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000,
                    "default": 100
                  }
                },
                "required": [
                  "slug",
                  "name",
                  "submissionsOpenAt",
                  "submissionsCloseAt",
                  "judgingOpenAt",
                  "judgingCloseAt"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Create an event and become its organizer.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        },
                        "prizes": {
                          "type": "string"
                        },
                        "questions": {
                          "type": "string"
                        },
                        "phase": {
                          "type": "string",
                          "enum": [
                            "upcoming",
                            "submissions",
                            "overlap",
                            "judging",
                            "between",
                            "finished"
                          ]
                        },
                        "submissionsOpen": {
                          "type": "boolean"
                        },
                        "judgingOpen": {
                          "type": "boolean"
                        },
                        "resultsPublic": {
                          "type": "boolean"
                        },
                        "archived": {
                          "type": "boolean"
                        },
                        "votingMode": {
                          "type": "string",
                          "enum": [
                            "off",
                            "open",
                            "account"
                          ]
                        },
                        "votingOpenAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCloseAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCredits": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "name",
                        "phase",
                        "votingMode",
                        "votingOpenAt",
                        "votingCloseAt",
                        "votingCredits"
                      ]
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "organizer"
                      ]
                    }
                  },
                  "required": [
                    "event",
                    "role"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.create",
        "x-manak-capability": {
          "audience": "founder"
        },
        "x-manak-records": [
          "event.created",
          "membership.granted"
        ],
        "x-manak-limit": "event"
      }
    },
    "/api/events/{event}": {
      "get": {
        "operationId": "events_show",
        "summary": "Describe one event, its clock and its tracks.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "events"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Describe one event, its clock and its tracks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        },
                        "prizes": {
                          "type": "string"
                        },
                        "questions": {
                          "type": "string"
                        },
                        "phase": {
                          "type": "string",
                          "enum": [
                            "upcoming",
                            "submissions",
                            "overlap",
                            "judging",
                            "between",
                            "finished"
                          ]
                        },
                        "submissionsOpen": {
                          "type": "boolean"
                        },
                        "judgingOpen": {
                          "type": "boolean"
                        },
                        "resultsPublic": {
                          "type": "boolean"
                        },
                        "archived": {
                          "type": "boolean"
                        },
                        "votingMode": {
                          "type": "string",
                          "enum": [
                            "off",
                            "open",
                            "account"
                          ]
                        },
                        "votingOpenAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCloseAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCredits": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "name",
                        "phase",
                        "votingMode",
                        "votingOpenAt",
                        "votingCloseAt",
                        "votingCredits"
                      ]
                    },
                    "clock": {
                      "type": "object",
                      "description": "Epoch milliseconds. The timezone is for display and nothing else.",
                      "properties": {
                        "submissionsOpenAt": {
                          "type": "integer"
                        },
                        "submissionsCloseAt": {
                          "type": "integer"
                        },
                        "judgingOpenAt": {
                          "type": "integer"
                        },
                        "judgingCloseAt": {
                          "type": "integer"
                        },
                        "nextBoundaryIn": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        }
                      }
                    },
                    "judging": {
                      "type": "object",
                      "properties": {
                        "reviewsPerProject": {
                          "type": "integer"
                        },
                        "pairwiseEnabled": {
                          "type": "boolean"
                        }
                      }
                    },
                    "tracks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "yourRoles": {
                      "type": "array",
                      "description": "Roles the caller holds here. Empty for a visitor, and not a refusal.",
                      "items": {
                        "type": "string",
                        "enum": [
                          "organizer",
                          "judge",
                          "participant"
                        ]
                      }
                    }
                  },
                  "required": [
                    "event",
                    "clock",
                    "judging",
                    "tracks",
                    "yourRoles"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.show",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "events_update",
        "summary": "Update this event's dates and judging settings.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "What people call it. “Dogfood Hackathon 2026”, not “dogfood-2026”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "timezone": {
                    "description": "An IANA zone such as Europe/Lisbon, used for displaying times. Every deadline is still one instant for everybody.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "default": "UTC"
                  },
                  "prizes": {
                    "description": "One prize per line, including its amount and eligibility.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "questions": {
                    "description": "One question per line. Teams answer these publicly on their project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "submissionsOpenAt": {
                    "description": "When teams may start submitting.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "submissionsCloseAt": {
                    "description": "The deadline. It is enforced to the millisecond.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingOpenAt": {
                    "description": "When judges may start scoring. It may be before submissions close.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingCloseAt": {
                    "description": "When scoring stops.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "reviewsPerProject": {
                    "description": "How many judges should see each project. Three is the usual answer; below three there is nothing to cross-check a lenient judge against.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "default": 3
                  },
                  "pairwiseEnabled": {
                    "description": "Ask judges which of two projects is better, as well as scoring each. It sharpens the top of the leaderboard and costs judges time.",
                    "type": "boolean",
                    "default": false
                  },
                  "votingOpenAt": {
                    "description": "When community voting begins.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingCloseAt": {
                    "description": "When community voting ends.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingMode": {
                    "description": "Choose off, open to a voter token, or signed-in accounts only.",
                    "type": "string",
                    "enum": [
                      "off",
                      "open",
                      "account"
                    ],
                    "default": "off"
                  },
                  "votingCredits": {
                    "description": "The quadratic voting budget per voter.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000,
                    "default": 100
                  }
                },
                "required": [
                  "name",
                  "submissionsOpenAt",
                  "submissionsCloseAt",
                  "judgingOpenAt",
                  "judgingCloseAt"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "description": "What people call it. “Dogfood Hackathon 2026”, not “dogfood-2026”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "timezone": {
                    "description": "An IANA zone such as Europe/Lisbon, used for displaying times. Every deadline is still one instant for everybody.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "default": "UTC"
                  },
                  "prizes": {
                    "description": "One prize per line, including its amount and eligibility.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "questions": {
                    "description": "One question per line. Teams answer these publicly on their project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "submissionsOpenAt": {
                    "description": "When teams may start submitting.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "submissionsCloseAt": {
                    "description": "The deadline. It is enforced to the millisecond.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingOpenAt": {
                    "description": "When judges may start scoring. It may be before submissions close.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "judgingCloseAt": {
                    "description": "When scoring stops.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "reviewsPerProject": {
                    "description": "How many judges should see each project. Three is the usual answer; below three there is nothing to cross-check a lenient judge against.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20,
                    "default": 3
                  },
                  "pairwiseEnabled": {
                    "description": "Ask judges which of two projects is better, as well as scoring each. It sharpens the top of the leaderboard and costs judges time.",
                    "type": "boolean",
                    "default": false
                  },
                  "votingOpenAt": {
                    "description": "When community voting begins.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingCloseAt": {
                    "description": "When community voting ends.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "votingMode": {
                    "description": "Choose off, open to a voter token, or signed-in accounts only.",
                    "type": "string",
                    "enum": [
                      "off",
                      "open",
                      "account"
                    ],
                    "default": "off"
                  },
                  "votingCredits": {
                    "description": "The quadratic voting budget per voter.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100000,
                    "default": 100
                  }
                },
                "required": [
                  "name",
                  "submissionsOpenAt",
                  "submissionsCloseAt",
                  "judgingOpenAt",
                  "judgingCloseAt"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update this event's dates and judging settings.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        },
                        "prizes": {
                          "type": "string"
                        },
                        "questions": {
                          "type": "string"
                        },
                        "phase": {
                          "type": "string",
                          "enum": [
                            "upcoming",
                            "submissions",
                            "overlap",
                            "judging",
                            "between",
                            "finished"
                          ]
                        },
                        "submissionsOpen": {
                          "type": "boolean"
                        },
                        "judgingOpen": {
                          "type": "boolean"
                        },
                        "resultsPublic": {
                          "type": "boolean"
                        },
                        "archived": {
                          "type": "boolean"
                        },
                        "votingMode": {
                          "type": "string",
                          "enum": [
                            "off",
                            "open",
                            "account"
                          ]
                        },
                        "votingOpenAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCloseAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "votingCredits": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "slug",
                        "name",
                        "phase",
                        "votingMode",
                        "votingOpenAt",
                        "votingCloseAt",
                        "votingCredits"
                      ]
                    }
                  },
                  "required": [
                    "event"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.update",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "event.updated"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/mine": {
      "get": {
        "operationId": "events_mine",
        "summary": "List the events the caller holds a role in.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "List the events the caller holds a role in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "event": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "slug": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "timezone": {
                                "type": "string"
                              },
                              "prizes": {
                                "type": "string"
                              },
                              "questions": {
                                "type": "string"
                              },
                              "phase": {
                                "type": "string",
                                "enum": [
                                  "upcoming",
                                  "submissions",
                                  "overlap",
                                  "judging",
                                  "between",
                                  "finished"
                                ]
                              },
                              "submissionsOpen": {
                                "type": "boolean"
                              },
                              "judgingOpen": {
                                "type": "boolean"
                              },
                              "resultsPublic": {
                                "type": "boolean"
                              },
                              "archived": {
                                "type": "boolean"
                              },
                              "votingMode": {
                                "type": "string",
                                "enum": [
                                  "off",
                                  "open",
                                  "account"
                                ]
                              },
                              "votingOpenAt": {
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "votingCloseAt": {
                                "type": [
                                  "integer",
                                  "null"
                                ]
                              },
                              "votingCredits": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "id",
                              "slug",
                              "name",
                              "phase",
                              "votingMode",
                              "votingOpenAt",
                              "votingCloseAt",
                              "votingCredits"
                            ]
                          },
                          "roles": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "organizer",
                                "judge",
                                "participant"
                              ]
                            }
                          }
                        },
                        "required": [
                          "event",
                          "roles"
                        ]
                      }
                    }
                  },
                  "required": [
                    "events"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.mine",
        "x-manak-capability": {
          "audience": "account"
        }
      }
    },
    "/api/events/{event}/invitations": {
      "post": {
        "operationId": "events_invite",
        "summary": "Send somebody a link that joins them to this event in a role.",
        "description": "Callable by a organizer of the event.\n\nThe response contains the invitation link. Organizer-only, and the ledger records who issued it, to which address and in which role.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "description": "The address to invite. It does not need an account here yet.",
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "role": {
                    "description": "What they will be able to do. A judge scores projects; a participant submits one; an organizer can do everything here, including inviting more organizers.",
                    "type": "string",
                    "enum": [
                      "organizer",
                      "judge",
                      "participant"
                    ]
                  }
                },
                "required": [
                  "email",
                  "role"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "description": "The address to invite. It does not need an account here yet.",
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "role": {
                    "description": "What they will be able to do. A judge scores projects; a participant submits one; an organizer can do everything here, including inviting more organizers.",
                    "type": "string",
                    "enum": [
                      "organizer",
                      "judge",
                      "participant"
                    ]
                  }
                },
                "required": [
                  "email",
                  "role"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Send somebody a link that joins them to this event in a role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "invited": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string",
                      "enum": [
                        "organizer",
                        "judge",
                        "participant"
                      ]
                    },
                    "link": {
                      "type": "string",
                      "description": "The invitation URL. Deliberately returned, unlike a sign-in link: an organizer may pass this on themselves. It works once."
                    },
                    "expiresAt": {
                      "type": "integer"
                    },
                    "alreadyHeld": {
                      "type": "boolean",
                      "description": "Whether this address already holds this role, making the link a resend."
                    }
                  },
                  "required": [
                    "invited",
                    "role",
                    "link",
                    "expiresAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.invite",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "invite.issued"
        ],
        "x-manak-limit": "invite"
      }
    },
    "/api/events/{event}/judges": {
      "get": {
        "operationId": "events_judges",
        "summary": "List the judges and organizers of this event.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only on purpose. Publishing a judge roster would let anybody un-blind the judging by reading a URL.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the judges and organizers of this event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "judges": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "joinedAt": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "id",
                          "email",
                          "displayName"
                        ]
                      }
                    },
                    "organizers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "displayName": {
                            "type": "string"
                          },
                          "joinedAt": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "id",
                          "email",
                          "displayName"
                        ]
                      }
                    },
                    "reviewsPerProject": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "judges",
                    "organizers",
                    "reviewsPerProject"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.judges",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/clock": {
      "get": {
        "operationId": "events_clock",
        "summary": "Inspect virtual event clock and time offsets.",
        "description": "Callable by a organizer of the event.\n\nReports real system time vs virtual offset time and current phase gates for demo evaluation.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Inspect virtual event clock and time offsets.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eventId": {
                      "type": "string"
                    },
                    "realNow": {
                      "type": "integer"
                    },
                    "virtualNow": {
                      "type": "integer"
                    },
                    "offsetMs": {
                      "type": "integer"
                    },
                    "phase": {
                      "type": "string"
                    },
                    "submissionsOpen": {
                      "type": "boolean"
                    },
                    "judgingOpen": {
                      "type": "boolean"
                    },
                    "resultsPublic": {
                      "type": "boolean"
                    },
                    "submissionsOpenAt": {
                      "type": "integer"
                    },
                    "submissionsCloseAt": {
                      "type": "integer"
                    },
                    "judgingOpenAt": {
                      "type": "integer"
                    },
                    "judgingCloseAt": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "eventId",
                    "realNow",
                    "virtualNow",
                    "offsetMs",
                    "phase",
                    "submissionsOpen",
                    "judgingOpen",
                    "resultsPublic",
                    "submissionsOpenAt",
                    "submissionsCloseAt",
                    "judgingOpenAt",
                    "judgingCloseAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.clock",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/clock/warp": {
      "post": {
        "operationId": "events_warp_clock",
        "summary": "Fast-forward or reset the virtual clock for demo and evaluation.",
        "description": "Callable by a organizer of the event.\n\nFast-forwards virtual time in-memory. Appends clock.warped audit ledger entry.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "targetPhase": {
                    "description": "Jump virtual clock directly into competition milestone.",
                    "type": "string",
                    "enum": [
                      "realtime",
                      "submissions",
                      "judging",
                      "results"
                    ]
                  },
                  "targetAt": {
                    "description": "Set virtual clock to an exact timestamp.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "offsetMs": {
                    "description": "Apply an explicit millisecond offset to real time.",
                    "type": "integer"
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "targetPhase": {
                    "description": "Jump virtual clock directly into competition milestone.",
                    "type": "string",
                    "enum": [
                      "realtime",
                      "submissions",
                      "judging",
                      "results"
                    ]
                  },
                  "targetAt": {
                    "description": "Set virtual clock to an exact timestamp.",
                    "oneOf": [
                      {
                        "type": "integer",
                        "description": "Epoch milliseconds."
                      },
                      {
                        "type": "string",
                        "format": "date-time"
                      }
                    ]
                  },
                  "offsetMs": {
                    "description": "Apply an explicit millisecond offset to real time.",
                    "type": "integer"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Fast-forward or reset the virtual clock for demo and evaluation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "offsetMs": {
                      "type": "integer"
                    },
                    "virtualNow": {
                      "type": "integer"
                    },
                    "phase": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "offsetMs",
                    "virtualNow",
                    "phase"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.warp_clock",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "clock.warped"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/webhooks": {
      "get": {
        "operationId": "events_webhooks",
        "summary": "Inspect webhook dispatch status, receiver configuration and signing specifications.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only. Provides HMAC-SHA256 signature specification and supported event action types.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Inspect webhook dispatch status, receiver configuration and signing specifications.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eventId": {
                      "type": "string"
                    },
                    "signatureAlgorithm": {
                      "type": "string"
                    },
                    "headerSignature": {
                      "type": "string"
                    },
                    "headerEvent": {
                      "type": "string"
                    },
                    "headerDelivery": {
                      "type": "string"
                    },
                    "supportedActions": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "eventId",
                    "signatureAlgorithm",
                    "headerSignature",
                    "headerEvent",
                    "headerDelivery",
                    "supportedActions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.webhooks",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/webhooks/ping": {
      "post": {
        "operationId": "events_ping_webhook",
        "summary": "Generate a signed webhook test payload without sending it.",
        "description": "Callable by a organizer of the event.\n\nGenerates a signed test payload locally and records it. Does not contact the supplied URL or verify delivery.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The HTTPS receiver endpoint.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "secret": {
                    "description": "Shared secret for HMAC-SHA256 signature verification (minimum 32 characters).",
                    "type": "string",
                    "minLength": 32,
                    "maxLength": 128
                  }
                },
                "required": [
                  "url",
                  "secret"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "description": "The HTTPS receiver endpoint.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "secret": {
                    "description": "Shared secret for HMAC-SHA256 signature verification (minimum 32 characters).",
                    "type": "string",
                    "minLength": 32,
                    "maxLength": 128
                  }
                },
                "required": [
                  "url",
                  "secret"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generate a signed webhook test payload without sending it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "deliveryId": {
                      "type": "string"
                    },
                    "signature": {
                      "type": "string"
                    },
                    "payload": {
                      "type": "string"
                    },
                    "delivered": {
                      "type": "boolean"
                    },
                    "statusCode": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "latencyMs": {
                      "type": "integer"
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "ok",
                    "deliveryId",
                    "signature",
                    "payload",
                    "delivered",
                    "latencyMs"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.ping_webhook",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "webhook.pinged"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/roles/revoke": {
      "post": {
        "operationId": "events_revoke_role",
        "summary": "Remove an event role while retaining its historical records.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "organizer",
                      "judge",
                      "participant"
                    ]
                  }
                },
                "required": [
                  "account",
                  "role"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "account": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "organizer",
                      "judge",
                      "participant"
                    ]
                  }
                },
                "required": [
                  "account",
                  "role"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remove an event role while retaining its historical records.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    },
                    "account": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "revoked",
                    "account",
                    "role"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.revoke_role",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "membership.revoked"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/projects/{project}/comments": {
      "post": {
        "operationId": "comments_add",
        "summary": "Comment on a submitted project.",
        "description": "Callable by any signed-in account.",
        "tags": [
          "comments"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  }
                },
                "required": [
                  "body"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Comment on a submitted project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "saved": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "saved"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "comments.add",
        "x-manak-capability": {
          "audience": "account",
          "scope": "event"
        },
        "x-manak-records": [
          "comment.created"
        ],
        "x-manak-limit": "vote"
      }
    },
    "/api/events/{event}/projects/{project}/comments/hide": {
      "post": {
        "operationId": "comments_hide",
        "summary": "Hide a project comment with an audited reason.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "comments"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "comment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20
                  },
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "comment",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "comment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20
                  },
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "comment",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Hide a project comment with an audited reason.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "hidden": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "hidden"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "comments.hide",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "comment.hidden"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/tracks": {
      "post": {
        "operationId": "tracks_create",
        "summary": "Add a track to an event.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "tracks"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "description": "Lower case, digits, hyphens and underscores. It appears in URLs and in the results table.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "label": {
                    "description": "What participants will see. “Best use of local models”, not “local-models”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "ordering": {
                    "description": "Lower numbers come first. Ties are broken by key, so leaving this alone lists them alphabetically.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 999,
                    "default": 0
                  }
                },
                "required": [
                  "key",
                  "label"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "description": "Lower case, digits, hyphens and underscores. It appears in URLs and in the results table.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "label": {
                    "description": "What participants will see. “Best use of local models”, not “local-models”.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "ordering": {
                    "description": "Lower numbers come first. Ties are broken by key, so leaving this alone lists them alphabetically.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 999,
                    "default": 0
                  }
                },
                "required": [
                  "key",
                  "label"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Add a track to an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "track": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        },
                        "ordering": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "key",
                        "label",
                        "ordering"
                      ]
                    }
                  },
                  "required": [
                    "track"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "tracks.create",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "track.created"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/teams": {
      "get": {
        "operationId": "teams_list",
        "summary": "List the teams in an event.",
        "description": "Callable by a participant of the event.",
        "tags": [
          "teams"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the teams in an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "teams": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "size": {
                            "type": "integer"
                          },
                          "yours": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "size",
                          "yours"
                        ]
                      }
                    },
                    "yours": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The id of the caller's team, if they are on one."
                    }
                  },
                  "required": [
                    "teams",
                    "yours"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "teams.list",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/teams/{team}/members": {
      "post": {
        "operationId": "teams_join",
        "summary": "Join a team in an event.",
        "description": "Callable by a participant of the event, while submissions are open.",
        "tags": [
          "teams"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "team",
            "in": "path",
            "required": true,
            "description": "The team's identifier, from the team list or from an invitation.",
            "schema": {
              "description": "The team's identifier, from the team list or from an invitation.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Join a team in an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "team": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "size": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "size"
                      ]
                    }
                  },
                  "required": [
                    "team"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "teams.join",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "gate": "submissions"
        },
        "x-manak-records": [
          "team.joined"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/teams/{team}/leave": {
      "post": {
        "operationId": "teams_leave",
        "summary": "Leave a team in an event.",
        "description": "Callable by a participant of the event, while submissions are open.",
        "tags": [
          "teams"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "team",
            "in": "path",
            "required": true,
            "description": "The team's identifier, from the team list or from an invitation.",
            "schema": {
              "description": "The team's identifier, from the team list or from an invitation.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Leave a team in an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "team": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "size": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "size"
                      ]
                    }
                  },
                  "required": [
                    "ok",
                    "team"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "teams.leave",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "gate": "submissions"
        },
        "x-manak-records": [
          "team.left"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/teams/{team}/invites/rotate": {
      "post": {
        "operationId": "teams_invite_rotate",
        "summary": "Rotate the private invitation link for this team.",
        "description": "Callable by a participant of the event, while submissions are open.",
        "tags": [
          "teams"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "team",
            "in": "path",
            "required": true,
            "description": "The team's identifier, from the team list or from an invitation.",
            "schema": {
              "description": "The team's identifier, from the team list or from an invitation.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotate the private invitation link for this team.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "teamId": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    },
                    "generation": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "teamId",
                    "code",
                    "generation"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "teams.invite_rotate",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "gate": "submissions"
        },
        "x-manak-records": [
          "team.invite_rotated"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/projects": {
      "get": {
        "operationId": "projects_list",
        "summary": "List the projects entered in an event.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "projects"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "trackKey",
            "in": "query",
            "required": false,
            "description": "Show only this track. Leave empty for all of them.",
            "schema": {
              "description": "Show only this track. Leave empty for all of them.",
              "type": "string",
              "minLength": 1,
              "maxLength": 40
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the projects entered in an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "teamId": {
                            "type": "string"
                          },
                          "teamName": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "tagline": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "thumbnailUrl": {
                            "type": "string"
                          },
                          "videoUrl": {
                            "type": "string"
                          },
                          "imageUrls": {
                            "type": "string"
                          },
                          "techTags": {
                            "type": "string"
                          },
                          "answers": {
                            "type": "string"
                          },
                          "repoUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "demoUrl": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "trackKey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "draft",
                              "submitted",
                              "withdrawn",
                              "disqualified"
                            ]
                          },
                          "createdAt": {
                            "type": "integer"
                          },
                          "savedAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "submittedAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "withdrawnAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "quarantined": {
                            "type": "boolean"
                          }
                        },
                        "required": [
                          "id",
                          "teamId",
                          "title",
                          "summary",
                          "status",
                          "createdAt"
                        ]
                      }
                    },
                    "visibility": {
                      "type": "string",
                      "enum": [
                        "public",
                        "team",
                        "organizer"
                      ],
                      "description": "Which slice of the event this list is. Only `organizer` is all of it."
                    },
                    "tracks": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "projects",
                    "visibility"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.list",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "projects_create",
        "summary": "Enter a project into an event.",
        "description": "Callable by a participant of the event, while submissions are open.\n\nSaves a draft. Nothing is entered until `projects.submit`, and the draft is visible only to the team and the organizers until then.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "teamName": {
                    "description": "Only needed the first time. Leave it empty to enter under your own name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "tagline": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "description": "Explain the problem, your approach, what works, and what you learned.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20000
                  },
                  "thumbnailUrl": {
                    "description": "Optional HTTPS image. The portal also works without external images.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "videoUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "imageUrls": {
                    "description": "Up to eight HTTPS image links, one per line.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16000
                  },
                  "techTags": {
                    "description": "Comma-separated tags, for example TypeScript, SQLite, WebCrypto.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000
                  },
                  "answers": {
                    "description": "Answer the organizer’s questions in order. These answers appear on your public project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  },
                  "title": {
                    "description": "What the judges will see at the top of the page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "summary": {
                    "description": "What you built and what it is for. This is the first thing a judge reads.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "repoUrl": {
                    "description": "An https link to the repository. Judges will open it.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "demoUrl": {
                    "description": "An https link to something running, or to a recording. Optional.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "trackKey": {
                    "description": "Which track to enter. Leave empty if the event has none.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                },
                "required": [
                  "title",
                  "summary"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "teamName": {
                    "description": "Only needed the first time. Leave it empty to enter under your own name.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "tagline": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "description": "Explain the problem, your approach, what works, and what you learned.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20000
                  },
                  "thumbnailUrl": {
                    "description": "Optional HTTPS image. The portal also works without external images.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "videoUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "imageUrls": {
                    "description": "Up to eight HTTPS image links, one per line.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16000
                  },
                  "techTags": {
                    "description": "Comma-separated tags, for example TypeScript, SQLite, WebCrypto.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000
                  },
                  "answers": {
                    "description": "Answer the organizer’s questions in order. These answers appear on your public project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  },
                  "title": {
                    "description": "What the judges will see at the top of the page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "summary": {
                    "description": "What you built and what it is for. This is the first thing a judge reads.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "repoUrl": {
                    "description": "An https link to the repository. Judges will open it.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "demoUrl": {
                    "description": "An https link to something running, or to a recording. Optional.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "trackKey": {
                    "description": "Which track to enter. Leave empty if the event has none.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                },
                "required": [
                  "title",
                  "summary"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enter a project into an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    },
                    "team": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "created": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "created"
                      ]
                    }
                  },
                  "required": [
                    "project",
                    "team"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.create",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "gate": "submissions"
        },
        "x-manak-records": [
          "team.created",
          "team.joined",
          "project.created"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/projects/{project}": {
      "get": {
        "operationId": "projects_show",
        "summary": "Show one project.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "projects"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show one project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    },
                    "team": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "size": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "size"
                      ]
                    },
                    "comments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "body": {
                            "type": "string"
                          },
                          "author": {
                            "type": "string"
                          },
                          "at": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "id",
                          "body",
                          "author",
                          "at"
                        ]
                      }
                    },
                    "yours": {
                      "type": "boolean"
                    },
                    "mayEdit": {
                      "type": "boolean"
                    },
                    "mayModerate": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "project",
                    "team",
                    "comments",
                    "yours",
                    "mayEdit",
                    "mayModerate"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.show",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "projects_update",
        "summary": "Replace a project's details.",
        "description": "Callable by a participant of the event, on the project's own team, while submissions are open.\n\nEvery field is sent, every time. An empty link or track clears it, because a form cannot tell the difference between a box somebody cleared and a field they left out.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tagline": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "description": "Explain the problem, your approach, what works, and what you learned.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20000
                  },
                  "thumbnailUrl": {
                    "description": "Optional HTTPS image. The portal also works without external images.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "videoUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "imageUrls": {
                    "description": "Up to eight HTTPS image links, one per line.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16000
                  },
                  "techTags": {
                    "description": "Comma-separated tags, for example TypeScript, SQLite, WebCrypto.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000
                  },
                  "answers": {
                    "description": "Answer the organizer’s questions in order. These answers appear on your public project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  },
                  "title": {
                    "description": "What the judges will see at the top of the page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "summary": {
                    "description": "What you built and what it is for. This is the first thing a judge reads.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "repoUrl": {
                    "description": "An https link to the repository. Judges will open it.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "demoUrl": {
                    "description": "An https link to something running, or to a recording. Optional.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "trackKey": {
                    "description": "Which track to enter. Leave empty if the event has none.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                },
                "required": [
                  "title",
                  "summary"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "tagline": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "description": {
                    "description": "Explain the problem, your approach, what works, and what you learned.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20000
                  },
                  "thumbnailUrl": {
                    "description": "Optional HTTPS image. The portal also works without external images.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "videoUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "imageUrls": {
                    "description": "Up to eight HTTPS image links, one per line.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16000
                  },
                  "techTags": {
                    "description": "Comma-separated tags, for example TypeScript, SQLite, WebCrypto.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 1000
                  },
                  "answers": {
                    "description": "Answer the organizer’s questions in order. These answers appear on your public project page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 12000
                  },
                  "title": {
                    "description": "What the judges will see at the top of the page.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "summary": {
                    "description": "What you built and what it is for. This is the first thing a judge reads.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "repoUrl": {
                    "description": "An https link to the repository. Judges will open it.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "demoUrl": {
                    "description": "An https link to something running, or to a recording. Optional.",
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2000
                  },
                  "trackKey": {
                    "description": "Which track to enter. Leave empty if the event has none.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                },
                "required": [
                  "title",
                  "summary"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replace a project's details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "project",
                    "changed"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.update",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "owner": "team",
          "gate": "submissions"
        },
        "x-manak-records": [
          "project.updated"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/projects/{project}/submit": {
      "post": {
        "operationId": "projects_submit",
        "summary": "Submit a project for judging.",
        "description": "Callable by a participant of the event, on the project's own team, while submissions are open.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Submit a project for judging.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    },
                    "msToSpare": {
                      "type": "integer",
                      "description": "Milliseconds between this submission and the deadline. It is also on the record."
                    }
                  },
                  "required": [
                    "project",
                    "msToSpare"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.submit",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "owner": "team",
          "gate": "submissions"
        },
        "x-manak-records": [
          "project.submitted"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/projects/{project}/withdraw": {
      "post": {
        "operationId": "projects_withdraw",
        "summary": "Withdraw a project from an event.",
        "description": "Callable by a participant of the event, on the project's own team, while submissions are open.\n\nReversible while submissions are open: submitting again clears the withdrawal.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "Optional, and only the organizers will read it.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "Optional, and only the organizers will read it.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Withdraw a project from an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    }
                  },
                  "required": [
                    "project"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.withdraw",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event",
          "owner": "team",
          "gate": "submissions"
        },
        "x-manak-records": [
          "project.withdrawn"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/projects/{project}/pull": {
      "post": {
        "operationId": "projects_pull",
        "summary": "Withdraw a project on a team's behalf.",
        "description": "Callable by a organizer of the event.\n\nFor a team that asked to be pulled. It is not a penalty and it is not recorded as one — use `projects.disqualify` when the finding is against the team.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Withdraw a project on a team's behalf.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    }
                  },
                  "required": [
                    "project"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.pull",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "project.withdrawn"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/projects/{project}/disqualify": {
      "post": {
        "operationId": "projects_disqualify",
        "summary": "Disqualify a project, with a stated reason.",
        "description": "Callable by a organizer of the event.\n\nThe reason is written to the ledger and shown to the team. There is no way to reverse it.",
        "tags": [
          "projects"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's identifier, as it appears in the URL.",
            "schema": {
              "description": "The project's identifier, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Disqualify a project, with a stated reason.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    }
                  },
                  "required": [
                    "project"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "projects.disqualify",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "project.disqualified"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/manage/duplicates": {
      "get": {
        "operationId": "duplicates_list",
        "summary": "Review quarantined project collisions.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "duplicates"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Review quarantined project collisions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "cases": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "cases"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "duplicates.list",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/manage/duplicates/triage": {
      "post": {
        "operationId": "duplicates_triage",
        "summary": "Confirm or clear a quarantined project.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "duplicates"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "description": "The project's identifier, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "confirmed",
                      "cleared"
                    ]
                  },
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "project",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "description": "The project's identifier, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "confirmed",
                      "cleared"
                    ]
                  },
                  "reason": {
                    "description": "The team will be shown this. It goes on the record either way.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "project",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Confirm or clear a quarantined project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "teamId": {
                          "type": "string"
                        },
                        "teamName": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "summary": {
                          "type": "string"
                        },
                        "tagline": {
                          "type": "string"
                        },
                        "description": {
                          "type": "string"
                        },
                        "thumbnailUrl": {
                          "type": "string"
                        },
                        "videoUrl": {
                          "type": "string"
                        },
                        "imageUrls": {
                          "type": "string"
                        },
                        "techTags": {
                          "type": "string"
                        },
                        "answers": {
                          "type": "string"
                        },
                        "repoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "demoUrl": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "trackKey": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "submitted",
                            "withdrawn",
                            "disqualified"
                          ]
                        },
                        "createdAt": {
                          "type": "integer"
                        },
                        "savedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "submittedAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "withdrawnAt": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "quarantined": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "id",
                        "teamId",
                        "title",
                        "summary",
                        "status",
                        "createdAt"
                      ]
                    }
                  },
                  "required": [
                    "project"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "duplicates.triage",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "project.duplicate_confirmed",
          "project.duplicate_cleared"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/rubric": {
      "get": {
        "operationId": "rubrics_show",
        "summary": "Show the rubric judges score against.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "rubrics"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "description": "Defaults to the published version.",
            "schema": {
              "description": "Defaults to the published version.",
              "type": "integer",
              "minimum": 1,
              "maximum": 10000
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show the rubric judges score against.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "published": {
                      "type": "boolean"
                    },
                    "criteria": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "weight": {
                            "type": "number"
                          },
                          "min": {
                            "type": "integer"
                          },
                          "max": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "key",
                          "label",
                          "weight",
                          "min",
                          "max"
                        ]
                      }
                    },
                    "totalWeight": {
                      "type": "number"
                    },
                    "mayEdit": {
                      "type": "boolean",
                      "description": "Whether the caller may write and publish versions. Draws forms; protects nothing."
                    },
                    "versions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "version": {
                            "type": "integer"
                          },
                          "published": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "version",
                          "published",
                          "createdAt"
                        ]
                      }
                    }
                  },
                  "required": [
                    "version",
                    "published",
                    "criteria",
                    "versions",
                    "mayEdit"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "rubrics.show",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "rubrics_create",
        "summary": "Write a new version of an event's rubric.",
        "description": "Callable by a organizer of the event.\n\nSaves a draft version. Judges score against the published version, so this changes nothing until `rubrics.publish`.",
        "tags": [
          "rubrics"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "criteria": {
                    "description": "One per line: key | Label | weight | min | max. The last three are optional and default to 1 | 1 | 5. Example: craft | Technical craft | 2 | 1 | 5",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  }
                },
                "required": [
                  "criteria"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "criteria": {
                    "description": "One per line: key | Label | weight | min | max. The last three are optional and default to 1 | 1 | 5. Example: craft | Technical craft | 2 | 1 | 5",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 8000
                  }
                },
                "required": [
                  "criteria"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Write a new version of an event's rubric.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "criteria": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "weight": {
                            "type": "number"
                          },
                          "min": {
                            "type": "integer"
                          },
                          "max": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "key",
                          "label",
                          "weight",
                          "min",
                          "max"
                        ]
                      }
                    }
                  },
                  "required": [
                    "version",
                    "criteria"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "rubrics.create",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "rubric.created"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/rubric/publish": {
      "post": {
        "operationId": "rubrics_publish",
        "summary": "Publish a rubric version for judges to score against.",
        "description": "Callable by a organizer of the event.\n\nThere is no way to unpublish. Write a new version and publish that instead.",
        "tags": [
          "rubrics"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "description": "Which version to publish. Rubrics are never edited, only superseded.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000
                  }
                },
                "required": [
                  "version"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "description": "Which version to publish. Rubrics are never edited, only superseded.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000
                  }
                },
                "required": [
                  "version"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Publish a rubric version for judges to score against.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    },
                    "criteria": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "weight": {
                            "type": "number"
                          },
                          "min": {
                            "type": "integer"
                          },
                          "max": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "key",
                          "label",
                          "weight",
                          "min",
                          "max"
                        ]
                      }
                    }
                  },
                  "required": [
                    "version",
                    "criteria"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "rubrics.publish",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "rubric.published"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/judging": {
      "get": {
        "operationId": "judging_queue",
        "summary": "The projects assigned to you, and how far you got with each.",
        "description": "Callable by a judge of the event.",
        "tags": [
          "judging"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "judge",
            "in": "query",
            "required": false,
            "description": "The judge whose queue or scores to inspect. Non-organizers may only inspect their own.",
            "schema": {
              "description": "The judge whose queue or scores to inspect. Non-organizers may only inspect their own.",
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          {
            "name": "focus",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The projects assigned to you, and how far you got with each.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "window": {
                      "type": "object",
                      "properties": {
                        "open": {
                          "type": "boolean"
                        },
                        "opensAt": {
                          "type": "integer"
                        },
                        "closesAt": {
                          "type": "integer"
                        },
                        "phase": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "open",
                        "opensAt",
                        "closesAt",
                        "phase"
                      ]
                    },
                    "rubric": {
                      "type": "object",
                      "properties": {
                        "version": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "criteria": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "weight": {
                                "type": "number"
                              },
                              "min": {
                                "type": "integer"
                              },
                              "max": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "key",
                              "label",
                              "weight",
                              "min",
                              "max"
                            ]
                          }
                        }
                      },
                      "required": [
                        "version",
                        "criteria"
                      ]
                    },
                    "pairwise": {
                      "type": "boolean"
                    },
                    "assigned": {
                      "type": "integer"
                    },
                    "submitted": {
                      "type": "integer"
                    },
                    "drafts": {
                      "type": "integer"
                    },
                    "comparisons": {
                      "type": "integer"
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "window",
                    "rubric",
                    "pairwise",
                    "assigned",
                    "submitted",
                    "drafts",
                    "projects"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "judging.queue",
        "x-manak-capability": {
          "audience": "judge",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/projects/{project}/ballot": {
      "post": {
        "operationId": "ballots_save",
        "summary": "Score a project against the published rubric.",
        "description": "Callable by a judge of the event, the judge the ballot belongs to, while judging is open.\n\nThe ballot is always filed as the signed-in judge; there is no way to enter one on another judge's behalf over HTTP. Saving again replaces the earlier ballot and records the revision. Scoring an unassigned project assigns it to you.",
        "tags": [
          "ballots"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's id, as it appears in the URL.",
            "schema": {
              "description": "The project's id, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scores": {
                    "description": "One whole number per criterion of the published rubric, keyed by criterion. From a form, send them as scores.<key> — a JSON client sends an object.",
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    }
                  },
                  "comment": {
                    "description": "What the team should hear. Organizers see this; whether the team does is their call.",
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 4000
                  },
                  "draft": {
                    "description": "A draft is not counted anywhere. Leave this off to file the ballot.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "scores": {
                    "description": "One whole number per criterion of the published rubric, keyed by criterion. From a form, send them as scores.<key> — a JSON client sends an object.",
                    "type": "object",
                    "additionalProperties": {
                      "type": "integer"
                    }
                  },
                  "comment": {
                    "description": "What the team should hear. Organizers see this; whether the team does is their call.",
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 4000
                  },
                  "draft": {
                    "description": "A draft is not counted anywhere. Leave this off to file the ballot.",
                    "type": "boolean",
                    "default": false
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Score a project against the published rubric.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "project": {
                      "type": "string"
                    },
                    "rubricVersion": {
                      "type": "integer"
                    },
                    "submitted": {
                      "type": "boolean"
                    },
                    "submittedAt": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "comment": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "scores": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "integer"
                      }
                    },
                    "assigned": {
                      "type": "integer"
                    },
                    "filed": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "id",
                    "project",
                    "rubricVersion",
                    "submitted",
                    "scores"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "ballots.save",
        "x-manak-capability": {
          "audience": "judge",
          "scope": "event",
          "owner": "judge",
          "gate": "judging"
        },
        "x-manak-records": [
          "assignment.created",
          "ballot.submitted",
          "ballot.revised"
        ],
        "x-manak-limit": "ballot"
      }
    },
    "/api/events/{event}/duel": {
      "get": {
        "operationId": "duels_next",
        "summary": "The next pair of projects for you to compare.",
        "description": "Callable by a judge of the event.",
        "tags": [
          "duels"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The next pair of projects for you to compare.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "window": {
                      "type": "object",
                      "properties": {
                        "open": {
                          "type": "boolean"
                        },
                        "opensAt": {
                          "type": "integer"
                        },
                        "closesAt": {
                          "type": "integer"
                        },
                        "phase": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "open",
                        "opensAt",
                        "closesAt",
                        "phase"
                      ]
                    },
                    "pairwise": {
                      "type": "boolean"
                    },
                    "filed": {
                      "type": "integer"
                    },
                    "pool": {
                      "type": "integer"
                    },
                    "connected": {
                      "type": "boolean"
                    },
                    "componentCount": {
                      "type": "integer"
                    },
                    "pair": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "left": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "teamId": {
                              "type": "string"
                            },
                            "teamName": {
                              "type": "string"
                            },
                            "title": {
                              "type": "string"
                            },
                            "summary": {
                              "type": "string"
                            },
                            "tagline": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            },
                            "thumbnailUrl": {
                              "type": "string"
                            },
                            "videoUrl": {
                              "type": "string"
                            },
                            "imageUrls": {
                              "type": "string"
                            },
                            "techTags": {
                              "type": "string"
                            },
                            "answers": {
                              "type": "string"
                            },
                            "repoUrl": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "demoUrl": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "trackKey": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "draft",
                                "submitted",
                                "withdrawn",
                                "disqualified"
                              ]
                            },
                            "createdAt": {
                              "type": "integer"
                            },
                            "savedAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "submittedAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "withdrawnAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "quarantined": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "id",
                            "teamId",
                            "title",
                            "summary",
                            "status",
                            "createdAt"
                          ]
                        },
                        "right": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "teamId": {
                              "type": "string"
                            },
                            "teamName": {
                              "type": "string"
                            },
                            "title": {
                              "type": "string"
                            },
                            "summary": {
                              "type": "string"
                            },
                            "tagline": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            },
                            "thumbnailUrl": {
                              "type": "string"
                            },
                            "videoUrl": {
                              "type": "string"
                            },
                            "imageUrls": {
                              "type": "string"
                            },
                            "techTags": {
                              "type": "string"
                            },
                            "answers": {
                              "type": "string"
                            },
                            "repoUrl": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "demoUrl": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "trackKey": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "draft",
                                "submitted",
                                "withdrawn",
                                "disqualified"
                              ]
                            },
                            "createdAt": {
                              "type": "integer"
                            },
                            "savedAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "submittedAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "withdrawnAt": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "quarantined": {
                              "type": "boolean"
                            }
                          },
                          "required": [
                            "id",
                            "teamId",
                            "title",
                            "summary",
                            "status",
                            "createdAt"
                          ]
                        },
                        "reason": {
                          "type": "string"
                        },
                        "information": {
                          "type": "number"
                        },
                        "deficit": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "required": [
                    "window",
                    "pairwise",
                    "filed",
                    "pool",
                    "pair"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "duels.next",
        "x-manak-capability": {
          "audience": "judge",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "duels_decide",
        "summary": "Record which of two projects is stronger.",
        "description": "Callable by a judge of the event, while judging is open.\n\nA skip is recorded rather than discarded: it does not move the ranking, but a judge skipping most of their duels is something an organizer needs to see. Deciding the same pair again replaces the earlier verdict and records the change.",
        "tags": [
          "duels"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "left": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "right": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "verdict": {
                    "description": "Which of the two shown projects is stronger, or skip if you cannot separate them.",
                    "type": "string",
                    "enum": [
                      "left",
                      "right",
                      "skip"
                    ]
                  },
                  "reason": {
                    "description": "The reason the pairing scheduler gave for this pair. Recorded, not trusted.",
                    "type": "string",
                    "enum": [
                      "bridge",
                      "informative",
                      "explore",
                      "exposure",
                      "manual"
                    ],
                    "default": "manual"
                  }
                },
                "required": [
                  "left",
                  "right",
                  "verdict"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "left": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "right": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "verdict": {
                    "description": "Which of the two shown projects is stronger, or skip if you cannot separate them.",
                    "type": "string",
                    "enum": [
                      "left",
                      "right",
                      "skip"
                    ]
                  },
                  "reason": {
                    "description": "The reason the pairing scheduler gave for this pair. Recorded, not trusted.",
                    "type": "string",
                    "enum": [
                      "bridge",
                      "informative",
                      "explore",
                      "exposure",
                      "manual"
                    ],
                    "default": "manual"
                  }
                },
                "required": [
                  "left",
                  "right",
                  "verdict"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record which of two projects is stronger.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "left": {
                      "type": "string"
                    },
                    "right": {
                      "type": "string"
                    },
                    "outcome": {
                      "type": "string",
                      "enum": [
                        "left",
                        "right",
                        "skip"
                      ]
                    },
                    "winner": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "filed": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "id",
                    "left",
                    "right",
                    "outcome",
                    "winner",
                    "filed"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "duels.decide",
        "x-manak-capability": {
          "audience": "judge",
          "scope": "event",
          "gate": "judging"
        },
        "x-manak-records": [
          "comparison.recorded",
          "comparison.revised"
        ],
        "x-manak-limit": "ballot"
      }
    },
    "/api/events/{event}/assignments": {
      "post": {
        "operationId": "assignments_draw",
        "summary": "Assign judges to projects, honouring conflicts and balancing the load.",
        "description": "Callable by a organizer of the event.\n\nUses the event's own reviews-per-project setting. Safe to run twice: the plan is applied as a difference. An assignment that already has a ballot against it is never removed.",
        "tags": [
          "assignments"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "track": {
                    "description": "Draw within one track only. Leave blank to draw the whole event.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "dryRun": {
                    "description": "Compute the plan and report shortfalls without writing any assignments.",
                    "type": "boolean",
                    "default": false
                  },
                  "expectedRevision": {
                    "description": "Prevents applying a plan after event evidence changes.",
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "track": {
                    "description": "Draw within one track only. Leave blank to draw the whole event.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "dryRun": {
                    "description": "Compute the plan and report shortfalls without writing any assignments.",
                    "type": "boolean",
                    "default": false
                  },
                  "expectedRevision": {
                    "description": "Prevents applying a plan after event evidence changes.",
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assign judges to projects, honouring conflicts and balancing the load.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "method": {
                      "type": "string"
                    },
                    "planRevision": {
                      "type": "string"
                    },
                    "applied": {
                      "type": "boolean"
                    },
                    "reviewsPerProject": {
                      "type": "integer"
                    },
                    "projects": {
                      "type": "integer"
                    },
                    "judges": {
                      "type": "integer"
                    },
                    "assignments": {
                      "type": "integer"
                    },
                    "added": {
                      "type": "integer"
                    },
                    "removed": {
                      "type": "integer"
                    },
                    "kept": {
                      "type": "integer"
                    },
                    "loadMin": {
                      "type": "integer"
                    },
                    "loadMax": {
                      "type": "integer"
                    },
                    "loadMean": {
                      "type": "number"
                    },
                    "balanced": {
                      "type": "boolean"
                    },
                    "complete": {
                      "type": "boolean"
                    },
                    "shortfalls": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "gaps": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "method",
                    "applied",
                    "reviewsPerProject",
                    "projects",
                    "judges",
                    "assignments",
                    "balanced",
                    "complete",
                    "shortfalls"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "assignments.draw",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "assignment.run",
          "assignment.created",
          "assignment.removed"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/assignments/preview": {
      "get": {
        "operationId": "assignments_preview",
        "summary": "Preview assignment coverage before applying a draw.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "assignments"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "track",
            "in": "query",
            "required": false,
            "description": "Draw within one track only. Leave blank to draw the whole event.",
            "schema": {
              "description": "Draw within one track only. Leave blank to draw the whole event.",
              "type": "string",
              "minLength": 1,
              "maxLength": 40
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Preview assignment coverage before applying a draw.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "method": {
                      "type": "string"
                    },
                    "planRevision": {
                      "type": "string"
                    },
                    "applied": {
                      "type": "boolean"
                    },
                    "reviewsPerProject": {
                      "type": "integer"
                    },
                    "projects": {
                      "type": "integer"
                    },
                    "judges": {
                      "type": "integer"
                    },
                    "assignments": {
                      "type": "integer"
                    },
                    "added": {
                      "type": "integer"
                    },
                    "removed": {
                      "type": "integer"
                    },
                    "kept": {
                      "type": "integer"
                    },
                    "loadMin": {
                      "type": "integer"
                    },
                    "loadMax": {
                      "type": "integer"
                    },
                    "loadMean": {
                      "type": "number"
                    },
                    "balanced": {
                      "type": "boolean"
                    },
                    "complete": {
                      "type": "boolean"
                    },
                    "shortfalls": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "gaps": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "method",
                    "applied",
                    "reviewsPerProject",
                    "projects",
                    "judges",
                    "assignments",
                    "balanced",
                    "complete",
                    "shortfalls"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "assignments.preview",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/judges/roster": {
      "get": {
        "operationId": "judges_roster",
        "summary": "List judge track, capacity, and recusal controls.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "judges"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List judge track, capacity, and recusal controls.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "judges": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "judges"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "judges.roster",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/judges/configure": {
      "post": {
        "operationId": "judges_configure",
        "summary": "Set one judge's eligible tracks and review capacity.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "judges"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "tracks": {
                    "description": "Comma separated. Leave blank for every track.",
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 2000
                  },
                  "capacity": {
                    "description": "Leave blank for no explicit limit. Zero pauses new assignments.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  }
                },
                "required": [
                  "judge"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "tracks": {
                    "description": "Comma separated. Leave blank for every track.",
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 2000
                  },
                  "capacity": {
                    "description": "Leave blank for no explicit limit. Zero pauses new assignments.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  }
                },
                "required": [
                  "judge"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set one judge's eligible tracks and review capacity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tracks": {
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "capacity": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "recusals": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "tracks",
                    "capacity",
                    "recusals"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "judges.configure",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "judge.configured"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/judges/recusal": {
      "post": {
        "operationId": "judges_recusal",
        "summary": "Record or clear a project recusal for one judge.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "judges"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "project": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "recuse",
                      "clear"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "judge",
                  "project",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "project": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "recuse",
                      "clear"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "judge",
                  "project",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record or clear a project recusal for one judge.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tracks": {
                      "type": [
                        "array",
                        "null"
                      ]
                    },
                    "capacity": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "recusals": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "tracks",
                    "capacity",
                    "recusals"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "judges.recusal",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "judge.recused",
          "judge.recusal_cleared",
          "assignment.removed",
          "assignment.run",
          "assignment.created"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/judging/{project}/recuse": {
      "post": {
        "operationId": "judges_self_recusal",
        "summary": "Leave an assigned project review and request an eligible replacement.",
        "description": "Callable by a judge of the event, while judging is open.",
        "tags": [
          "judges"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "description": "The project's id, as it appears in the URL.",
            "schema": {
              "description": "The project's id, as it appears in the URL.",
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Leave an assigned project review and request an eligible replacement.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "recusals": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "topUp": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "recusals",
                    "topUp"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "judges.self_recusal",
        "x-manak-capability": {
          "audience": "judge",
          "scope": "event",
          "gate": "judging"
        },
        "x-manak-records": [
          "judge.recused",
          "assignment.removed",
          "assignment.run",
          "assignment.created"
        ],
        "x-manak-limit": "ballot"
      }
    },
    "/api/events/{event}/review-requests": {
      "get": {
        "operationId": "reviews_requests",
        "summary": "List targeted additional review requests and completion state.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "reviews"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List targeted additional review requests and completion state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requests": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "requests"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "reviews.requests",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "reviews_request",
        "summary": "Assign one additional eligible judge to a submitted project.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "reviews"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "reasonCode": {
                    "type": "string",
                    "enum": [
                      "coverage",
                      "fragility",
                      "appeal",
                      "other"
                    ]
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "priority": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3,
                    "default": 2
                  },
                  "dueAt": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "project",
                  "reasonCode",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "description": "The project's id, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "reasonCode": {
                    "type": "string",
                    "enum": [
                      "coverage",
                      "fragility",
                      "appeal",
                      "other"
                    ]
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "priority": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 3,
                    "default": 2
                  },
                  "dueAt": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "project",
                  "reasonCode",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Assign one additional eligible judge to a submitted project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "project": {
                      "type": "string"
                    },
                    "judge": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "project",
                    "judge"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "reviews.request",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "review.requested",
          "assignment.created"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/review-requests/{request}/cancel": {
      "post": {
        "operationId": "reviews_cancel",
        "summary": "Cancel an unfinished targeted review request.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "reviews"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "request",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancel an unfinished targeted review request.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "state"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "reviews.cancel",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "review.cancelled",
          "assignment.removed"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/dashboard": {
      "get": {
        "operationId": "events_dashboard",
        "summary": "Show judging progress, coverage and judge effects for an event.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only. The judge-effect table is here and nowhere else: `results.show` publishes per-project `rankMove` instead, which shows that normalization happened without naming a judge. `reliability` and `criteria` are the read-only passes over the fit — uncertainty and tiers, and what each line of the rubric is doing. `results.show` gets the anonymous half of the first and none of the second. `calibration` is the pre-publish read on the panel itself: one row per judge with a verdict on whether their part of it is ready, and the judge pairs who agreed more than these comparisons predict. It is the only place in the product that prints a verdict about a person, and it reaches no public surface at any role. Because it exists, `rubric.warnings` is panel-level whenever `calibration` is not null: a sentence about one judge belongs in that judge's row, with the action beside it, rather than twice on one page.",
        "tags": [
          "events"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "lab",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "finalists",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 3
            }
          },
          {
            "name": "sensitivity",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show judging progress, coverage and judge effects for an event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "evidenceLab": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "Opt-in bounded diagnostics: Fisher information geometry, Hodge decomposition, W2 reviewer distributions, and vote signals. Organizer-only; no ranking changes. Cached by ledger revision.",
                      "properties": {
                        "information": {
                          "type": "object",
                          "required": [
                            "status",
                            "report"
                          ],
                          "properties": {
                            "status": {
                              "type": "string",
                              "enum": [
                                "ready",
                                "ill-conditioned",
                                "limit",
                                "needs-converged-fit"
                              ]
                            },
                            "report": {
                              "type": [
                                "object",
                                "null"
                              ],
                              "description": "Likelihood-only Fisher Laplacian. Relative SE is local model curvature, not calibrated confidence; cross-component contrasts are null.",
                              "properties": {
                                "method": {
                                  "type": "string"
                                },
                                "projectCount": {
                                  "type": "integer"
                                },
                                "componentCount": {
                                  "type": "integer"
                                },
                                "identifiableContrasts": {
                                  "type": "integer"
                                },
                                "solveResidual": {
                                  "type": "number"
                                },
                                "leverageSum": {
                                  "type": "number"
                                },
                                "leverageError": {
                                  "type": "number"
                                },
                                "numericallySound": {
                                  "type": "boolean"
                                },
                                "pairs": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "left": {
                                        "type": "string"
                                      },
                                      "right": {
                                        "type": "string"
                                      },
                                      "comparisons": {
                                        "type": "integer"
                                      },
                                      "resistance": {
                                        "type": [
                                          "number",
                                          "null"
                                        ]
                                      },
                                      "relativeSE": {
                                        "type": [
                                          "number",
                                          "null"
                                        ]
                                      },
                                      "informationGain": {
                                        "type": [
                                          "number",
                                          "null"
                                        ]
                                      },
                                      "leverage": {
                                        "type": [
                                          "number",
                                          "null"
                                        ]
                                      },
                                      "reason": {
                                        "type": "string",
                                        "enum": [
                                          "bridge",
                                          "information"
                                        ]
                                      }
                                    }
                                  }
                                },
                                "recommendations": {
                                  "type": "array",
                                  "items": {
                                    "type": "object"
                                  },
                                  "description": "At most eight individual candidate comparisons. Conflicts, track scope and repeat limits must still be enforced by the scheduler."
                                },
                                "bottlenecks": {
                                  "type": "array",
                                  "items": {
                                    "type": "object"
                                  }
                                },
                                "note": {
                                  "type": "string"
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "readiness": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "enum": [
                            "needs-evidence",
                            "review-needed",
                            "checks-passed"
                          ]
                        },
                        "passed": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "missing": {
                          "type": "integer"
                        },
                        "review": {
                          "type": "integer"
                        },
                        "note": {
                          "type": "string"
                        },
                        "checks": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "pass",
                                  "review",
                                  "missing"
                                ]
                              },
                              "title": {
                                "type": "string"
                              },
                              "detail": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "code",
                              "status",
                              "title",
                              "detail"
                            ]
                          }
                        }
                      },
                      "required": [
                        "status",
                        "passed",
                        "total",
                        "missing",
                        "review",
                        "note",
                        "checks"
                      ]
                    },
                    "window": {
                      "type": "object",
                      "properties": {
                        "phase": {
                          "type": "string"
                        },
                        "submissionsOpen": {
                          "type": "boolean"
                        },
                        "judgingOpen": {
                          "type": "boolean"
                        },
                        "resultsPublic": {
                          "type": "boolean"
                        },
                        "archived": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "phase",
                        "submissionsOpen",
                        "judgingOpen",
                        "resultsPublic"
                      ]
                    },
                    "counts": {
                      "type": "object",
                      "properties": {
                        "projects": {
                          "type": "integer"
                        },
                        "judges": {
                          "type": "integer"
                        },
                        "assignments": {
                          "type": "integer"
                        },
                        "ballots": {
                          "type": "integer"
                        },
                        "drafts": {
                          "type": "integer"
                        },
                        "comparisons": {
                          "type": "integer"
                        },
                        "skipped": {
                          "type": "integer"
                        },
                        "reviewsPerProject": {
                          "type": "integer"
                        },
                        "shortProjects": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "projects",
                        "judges",
                        "ballots",
                        "comparisons",
                        "reviewsPerProject"
                      ]
                    },
                    "rubric": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "version": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "method": {
                          "type": "string"
                        },
                        "rounds": {
                          "type": "integer"
                        },
                        "converged": {
                          "type": "boolean"
                        },
                        "grandMean": {
                          "type": "number"
                        },
                        "residualSd": {
                          "type": "number"
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "judges": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "judge": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "email": {
                            "type": "string"
                          },
                          "assigned": {
                            "type": "integer"
                          },
                          "submitted": {
                            "type": "integer"
                          },
                          "drafts": {
                            "type": "integer"
                          },
                          "comparisons": {
                            "type": "integer"
                          },
                          "skipped": {
                            "type": "integer"
                          },
                          "lastActiveAt": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "judge",
                          "name",
                          "assigned",
                          "submitted",
                          "drafts",
                          "comparisons",
                          "skipped"
                        ]
                      }
                    },
                    "effects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "judge": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "ballots": {
                            "type": "integer"
                          },
                          "leniency": {
                            "type": "number"
                          },
                          "scale": {
                            "type": "number"
                          },
                          "scaleRaw": {
                            "type": "number"
                          },
                          "shrinkage": {
                            "type": "number"
                          },
                          "informationWeight": {
                            "type": "number"
                          },
                          "clamped": {
                            "type": "boolean"
                          },
                          "discrimination": {
                            "type": "string",
                            "enum": [
                              "ok",
                              "low",
                              "insufficient"
                            ]
                          }
                        },
                        "required": [
                          "judge",
                          "name",
                          "ballots",
                          "leniency",
                          "scale",
                          "shrinkage",
                          "discrimination"
                        ]
                      }
                    },
                    "reliability": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "varianceShare": {
                          "type": "object",
                          "properties": {
                            "project": {
                              "type": "number"
                            },
                            "judge": {
                              "type": "number"
                            },
                            "residual": {
                              "type": "number"
                            }
                          },
                          "required": [
                            "project",
                            "judge",
                            "residual"
                          ]
                        },
                        "projectSd": {
                          "type": "number"
                        },
                        "judgeSd": {
                          "type": "number"
                        },
                        "residualSd": {
                          "type": "number"
                        },
                        "trueSd": {
                          "type": "number"
                        },
                        "errorSd": {
                          "type": "number"
                        },
                        "separation": {
                          "type": "number"
                        },
                        "strata": {
                          "type": "number"
                        },
                        "reliability": {
                          "type": "number"
                        },
                        "ballotsPerProject": {
                          "type": "number"
                        },
                        "confidence": {
                          "type": "number"
                        },
                        "tMultiplier": {
                          "type": "number"
                        },
                        "df": {
                          "type": "number"
                        },
                        "tiers": {
                          "type": "integer"
                        },
                        "decisive": {
                          "type": "boolean"
                        },
                        "intervals": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "trackKey": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "adjusted": {
                                "type": "number"
                              },
                              "standardError": {
                                "type": "number"
                              },
                              "low": {
                                "type": "number"
                              },
                              "high": {
                                "type": "number"
                              },
                              "halfWidth": {
                                "type": "number"
                              },
                              "tier": {
                                "type": "integer"
                              },
                              "sharesTier": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "adjusted",
                              "low",
                              "high",
                              "tier",
                              "sharesTier"
                            ]
                          }
                        },
                        "outliers": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "judge": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "observed": {
                                "type": "number"
                              },
                              "expected": {
                                "type": "number"
                              },
                              "residual": {
                                "type": "number"
                              },
                              "z": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "judge",
                              "name",
                              "project",
                              "title",
                              "observed",
                              "expected",
                              "residual",
                              "z"
                            ]
                          }
                        },
                        "judges": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "judge": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "ballots": {
                                "type": "integer"
                              },
                              "residualSd": {
                                "type": "number"
                              },
                              "relative": {
                                "type": "number"
                              },
                              "bias": {
                                "type": "number"
                              },
                              "flagged": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "judge",
                              "name",
                              "ballots",
                              "residualSd",
                              "relative",
                              "bias",
                              "flagged"
                            ]
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "info",
                                  "warn"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "subjects": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "The ids the note is about, for a client that wants to highlight rows. Project ids stay ids here while the message names titles, because these are the machine-readable half; judge ids are replaced on both, on every public surface."
                              }
                            },
                            "required": [
                              "code",
                              "severity",
                              "message",
                              "subjects"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "varianceShare",
                        "separation",
                        "strata",
                        "reliability",
                        "tiers",
                        "decisive",
                        "intervals",
                        "outliers",
                        "judges",
                        "warnings"
                      ]
                    },
                    "criteria": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "criteria": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "weight": {
                                "type": "number"
                              },
                              "scaleMin": {
                                "type": "number"
                              },
                              "scaleMax": {
                                "type": "number"
                              },
                              "ballots": {
                                "type": "integer"
                              },
                              "observedMean": {
                                "type": "number"
                              },
                              "observedSd": {
                                "type": "number"
                              },
                              "observedMin": {
                                "type": "number"
                              },
                              "observedMax": {
                                "type": "number"
                              },
                              "rangeUsed": {
                                "type": "number"
                              },
                              "discrimination": {
                                "type": "number"
                              },
                              "judgeSpread": {
                                "type": "number"
                              },
                              "judgeDivergence": {
                                "type": "number"
                              },
                              "withTotal": {
                                "type": "number"
                              },
                              "withRanking": {
                                "type": "number"
                              },
                              "verdict": {
                                "type": "string",
                                "enum": [
                                  "discriminating",
                                  "weak",
                                  "flat"
                                ]
                              }
                            },
                            "required": [
                              "key",
                              "label",
                              "weight",
                              "ballots",
                              "rangeUsed",
                              "discrimination",
                              "verdict"
                            ]
                          }
                        },
                        "redundant": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "a": {
                                "type": "string"
                              },
                              "b": {
                                "type": "string"
                              },
                              "correlation": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "a",
                              "b",
                              "correlation"
                            ]
                          }
                        },
                        "meanCorrelation": {
                          "type": "number"
                        },
                        "contested": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "info",
                                  "warn"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "subjects": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "The ids the note is about, for a client that wants to highlight rows. Project ids stay ids here while the message names titles, because these are the machine-readable half; judge ids are replaced on both, on every public surface."
                              }
                            },
                            "required": [
                              "code",
                              "severity",
                              "message",
                              "subjects"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "criteria",
                        "redundant",
                        "meanCorrelation",
                        "contested",
                        "warnings"
                      ]
                    },
                    "calibration": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "judges": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "judge": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "assigned": {
                                "type": "integer"
                              },
                              "submitted": {
                                "type": "integer"
                              },
                              "drafts": {
                                "type": "integer"
                              },
                              "outstanding": {
                                "type": "integer"
                              },
                              "ballots": {
                                "type": "integer"
                              },
                              "centre": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "spanUsed": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "leniency": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "leniencyShare": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "scale": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "discrimination": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "enum": [
                                  "ok",
                                  "low",
                                  "insufficient",
                                  null
                                ]
                              },
                              "spreadRelative": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "noisy": {
                                "type": "boolean"
                              },
                              "outliers": {
                                "type": "integer"
                              },
                              "comparisons": {
                                "type": "integer"
                              },
                              "skipped": {
                                "type": "integer"
                              },
                              "agreed": {
                                "type": "integer"
                              },
                              "against": {
                                "type": "integer"
                              },
                              "agreement": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "expectedAgreement": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "surprise": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "surpriseRatio": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "heldOut": {
                                "type": "boolean"
                              },
                              "closedTriples": {
                                "type": "integer"
                              },
                              "cycles": {
                                "type": "integer"
                              },
                              "cycleRate": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "findings": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                }
                              },
                              "verdict": {
                                "type": "string",
                                "enum": [
                                  "ok",
                                  "thin",
                                  "behind",
                                  "check"
                                ]
                              },
                              "action": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "judge",
                              "name",
                              "assigned",
                              "submitted",
                              "outstanding",
                              "ballots",
                              "comparisons",
                              "skipped",
                              "heldOut",
                              "findings",
                              "verdict",
                              "action"
                            ]
                          }
                        },
                        "blocs": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "a": {
                                "type": "string"
                              },
                              "b": {
                                "type": "string"
                              },
                              "aName": {
                                "type": "string"
                              },
                              "bName": {
                                "type": "string"
                              },
                              "shared": {
                                "type": "integer"
                              },
                              "agreed": {
                                "type": "integer"
                              },
                              "share": {
                                "type": "number"
                              },
                              "expected": {
                                "type": "number"
                              },
                              "excess": {
                                "type": "number"
                              },
                              "pValue": {
                                "type": "number"
                              },
                              "level": {
                                "type": "number"
                              },
                              "asked": {
                                "type": "boolean"
                              }
                            },
                            "required": [
                              "a",
                              "b",
                              "aName",
                              "bName",
                              "shared",
                              "agreed",
                              "share",
                              "expected",
                              "excess",
                              "pValue",
                              "level",
                              "asked"
                            ]
                          }
                        },
                        "panelSurprise": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "heldOut": {
                          "type": "integer"
                        },
                        "inSample": {
                          "type": "integer"
                        },
                        "panelExcess": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "blocLevel": {
                          "type": "number"
                        },
                        "span": {
                          "type": "number"
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "info",
                                  "warn"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "subjects": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "The ids the note is about, for a client that wants to highlight rows. Project ids stay ids here while the message names titles, because these are the machine-readable half; judge ids are replaced on both, on every public surface."
                              }
                            },
                            "required": [
                              "code",
                              "severity",
                              "message",
                              "subjects"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "judges",
                        "blocs",
                        "heldOut",
                        "inSample",
                        "blocLevel",
                        "span",
                        "warnings"
                      ]
                    },
                    "coverage": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "trackKey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "assigned": {
                            "type": "integer"
                          },
                          "submitted": {
                            "type": "integer"
                          },
                          "drafts": {
                            "type": "integer"
                          },
                          "target": {
                            "type": "integer"
                          },
                          "short": {
                            "type": "integer"
                          },
                          "comparisons": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "project",
                          "title",
                          "assigned",
                          "submitted",
                          "target",
                          "short"
                        ]
                      }
                    },
                    "gaps": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "trackKey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "assigned": {
                            "type": "integer"
                          },
                          "submitted": {
                            "type": "integer"
                          },
                          "drafts": {
                            "type": "integer"
                          },
                          "target": {
                            "type": "integer"
                          },
                          "short": {
                            "type": "integer"
                          },
                          "comparisons": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "project",
                          "title",
                          "assigned",
                          "submitted",
                          "target",
                          "short"
                        ]
                      }
                    },
                    "pairing": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "pairwise": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "converged": {
                          "type": "boolean"
                        },
                        "iterations": {
                          "type": "integer"
                        },
                        "connected": {
                          "type": "boolean"
                        },
                        "componentCount": {
                          "type": "integer"
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "strengths": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "trackKey": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "beta": {
                                "type": "number"
                              },
                              "wins": {
                                "type": "integer"
                              },
                              "losses": {
                                "type": "integer"
                              },
                              "comparisons": {
                                "type": "integer"
                              },
                              "rank": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "beta",
                              "wins",
                              "losses",
                              "comparisons",
                              "rank"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "converged",
                        "connected",
                        "componentCount",
                        "strengths"
                      ]
                    },
                    "agreement": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "tau": {
                          "type": "number"
                        },
                        "threshold": {
                          "type": "integer"
                        },
                        "medianGap": {
                          "type": "number"
                        },
                        "flaggedCount": {
                          "type": "integer"
                        },
                        "topOverlap": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "k": {
                                "type": "integer"
                              },
                              "overlap": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "k",
                              "overlap"
                            ]
                          }
                        },
                        "disagreements": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "rubricRank": {
                                "type": "integer"
                              },
                              "pairwiseRank": {
                                "type": "integer"
                              },
                              "rankGap": {
                                "type": "integer"
                              },
                              "ballots": {
                                "type": "integer"
                              },
                              "comparisons": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "rubricRank",
                              "pairwiseRank",
                              "rankGap"
                            ]
                          }
                        },
                        "rubricOnly": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "pairwiseOnly": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "tau",
                        "threshold",
                        "medianGap",
                        "flaggedCount",
                        "topOverlap",
                        "disagreements"
                      ]
                    },
                    "multiModel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "trackKey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ballots": {
                            "type": "integer"
                          },
                          "comparisons": {
                            "type": "integer"
                          },
                          "rawMean": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "rawRank": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "calibratedScore": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "calibratedRank": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "btStrength": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "btRank": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "rankShift": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "project",
                          "title",
                          "ballots",
                          "comparisons"
                        ]
                      }
                    },
                    "decisionSupport": {
                      "type": "object",
                      "properties": {
                        "target": {
                          "type": "integer"
                        },
                        "decisive": {
                          "type": "boolean"
                        },
                        "candidates": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "trackKey": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "guaranteed",
                                  "bubble",
                                  "eliminated"
                                ]
                              },
                              "rank": {
                                "type": "number"
                              },
                              "fitted": {
                                "type": "number"
                              },
                              "low": {
                                "type": "number"
                              },
                              "high": {
                                "type": "number"
                              },
                              "spread": {
                                "type": "number"
                              },
                              "reviews": {
                                "type": "integer"
                              },
                              "verdict": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "duels": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "left": {
                                "type": "string"
                              },
                              "right": {
                                "type": "string"
                              },
                              "reason": {
                                "type": "string"
                              }
                            }
                          }
                        },
                        "sensitivity": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "description": "Optional bounded leave-one-judge-out refits, diagnostics only."
                        }
                      }
                    },
                    "audit": {
                      "type": "object",
                      "properties": {
                        "head": {
                          "type": "string"
                        },
                        "entries": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "seq": {
                                "type": "integer"
                              },
                              "at": {
                                "type": "integer"
                              },
                              "action": {
                                "type": "string"
                              },
                              "actor": {
                                "type": "string"
                              },
                              "subject": {
                                "type": "string"
                              },
                              "payload": {
                                "type": "string"
                              },
                              "hash": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "window",
                    "counts",
                    "judges",
                    "effects",
                    "coverage",
                    "gaps"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "events.dashboard",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results": {
      "get": {
        "operationId": "results_show",
        "summary": "Show the ranking, once an organizer has published it.",
        "description": "Callable by anyone, signed in or not.\n\nOrganizers can read this before publishing, as a preview. Everybody else gets `results.notPublic` until `results.publish` has been called. Judge leniency and scale are not on this response at any role: see `events.dashboard`. `panel` and the per-project `tier` say how much of the order the evidence supports: a tier holds the projects that are not separated from the one at the top of it.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "revision",
            "in": "query",
            "required": false,
            "description": "Leave blank for the latest frozen publication.",
            "schema": {
              "description": "Leave blank for the latest frozen publication.",
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Show the ranking, once an organizer has published it.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "slug",
                        "name"
                      ]
                    },
                    "published": {
                      "type": "boolean"
                    },
                    "revision": {
                      "type": "integer"
                    },
                    "evidenceCutoffAt": {
                      "type": "integer"
                    },
                    "evidenceDigest": {
                      "type": "string"
                    },
                    "mayPublish": {
                      "type": "boolean"
                    },
                    "method": {
                      "type": "string"
                    },
                    "rubricVersion": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "ballots": {
                      "type": "integer"
                    },
                    "comparisonsDecided": {
                      "type": "integer"
                    },
                    "converged": {
                      "type": "boolean"
                    },
                    "grandMean": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "residualSd": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "trackKey": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "ballots": {
                            "type": "integer"
                          },
                          "rawMean": {
                            "type": "number"
                          },
                          "standardError": {
                            "type": "number"
                          },
                          "adjusted": {
                            "type": "number"
                          },
                          "rank": {
                            "type": "integer"
                          },
                          "rankRaw": {
                            "type": "integer"
                          },
                          "rankMove": {
                            "type": "integer"
                          },
                          "low": {
                            "type": "number"
                          },
                          "high": {
                            "type": "number"
                          },
                          "halfWidth": {
                            "type": "number"
                          },
                          "tier": {
                            "type": "integer"
                          },
                          "sharesTier": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "project",
                          "title",
                          "ballots",
                          "adjusted",
                          "rank",
                          "rankRaw",
                          "rankMove"
                        ]
                      }
                    },
                    "panel": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "varianceShare": {
                          "type": "object",
                          "properties": {
                            "project": {
                              "type": "number"
                            },
                            "judge": {
                              "type": "number"
                            },
                            "residual": {
                              "type": "number"
                            }
                          },
                          "required": [
                            "project",
                            "judge",
                            "residual"
                          ]
                        },
                        "projectSd": {
                          "type": "number"
                        },
                        "judgeSd": {
                          "type": "number"
                        },
                        "residualSd": {
                          "type": "number"
                        },
                        "trueSd": {
                          "type": "number"
                        },
                        "errorSd": {
                          "type": "number"
                        },
                        "separation": {
                          "type": "number"
                        },
                        "strata": {
                          "type": "number"
                        },
                        "reliability": {
                          "type": "number"
                        },
                        "ballotsPerProject": {
                          "type": "number"
                        },
                        "confidence": {
                          "type": "number"
                        },
                        "tMultiplier": {
                          "type": "number"
                        },
                        "df": {
                          "type": "number"
                        },
                        "tiers": {
                          "type": "integer"
                        },
                        "decisive": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "method",
                        "varianceShare",
                        "separation",
                        "strata",
                        "reliability",
                        "tiers",
                        "decisive"
                      ]
                    },
                    "pairwise": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "converged": {
                          "type": "boolean"
                        },
                        "iterations": {
                          "type": "integer"
                        },
                        "connected": {
                          "type": "boolean"
                        },
                        "componentCount": {
                          "type": "integer"
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "strengths": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "trackKey": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "beta": {
                                "type": "number"
                              },
                              "wins": {
                                "type": "integer"
                              },
                              "losses": {
                                "type": "integer"
                              },
                              "comparisons": {
                                "type": "integer"
                              },
                              "rank": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "beta",
                              "wins",
                              "losses",
                              "comparisons",
                              "rank"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "converged",
                        "connected",
                        "componentCount",
                        "strengths"
                      ]
                    },
                    "agreement": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "tau": {
                          "type": "number"
                        },
                        "threshold": {
                          "type": "integer"
                        },
                        "medianGap": {
                          "type": "number"
                        },
                        "flaggedCount": {
                          "type": "integer"
                        },
                        "topOverlap": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "k": {
                                "type": "integer"
                              },
                              "overlap": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "k",
                              "overlap"
                            ]
                          }
                        },
                        "disagreements": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "rubricRank": {
                                "type": "integer"
                              },
                              "pairwiseRank": {
                                "type": "integer"
                              },
                              "rankGap": {
                                "type": "integer"
                              },
                              "ballots": {
                                "type": "integer"
                              },
                              "comparisons": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "rubricRank",
                              "pairwiseRank",
                              "rankGap"
                            ]
                          }
                        },
                        "rubricOnly": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "pairwiseOnly": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "tau",
                        "threshold",
                        "medianGap",
                        "flaggedCount",
                        "topOverlap",
                        "disagreements"
                      ]
                    }
                  },
                  "required": [
                    "event",
                    "published",
                    "method",
                    "ballots",
                    "comparisonsDecided",
                    "converged",
                    "warnings",
                    "projects"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.show",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results/confidence": {
      "get": {
        "operationId": "results_confidence",
        "summary": "Say which parts of the duel ranking the comparisons establish, and which are a tie.",
        "description": "Callable by anyone, signed in or not.\n\nResamples the panel to ask whether another panel would have produced this order. `pairs` is the answer to \"is first place real\": a pair with `ordered: false` is two projects the comparisons cannot separate, however far apart they sit in the table. A `tier` holds the projects that are not separated from the one at the top of it, which is the unit to award on; two projects can share a tier and still be separated from each other, so `pairs` is where a boundary is established. Organizers can read this before publishing; everybody else gets `results.notPublic` until then. Costs about a second and is limited to 20 a minute per event.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "replicates",
            "in": "query",
            "required": false,
            "description": "How many times to refit the ranking on resampled data. More is finer and slower; the default resolves a quarter of a percentage point.",
            "schema": {
              "description": "How many times to refit the ranking on resampled data. More is finer and slower; the default resolves a quarter of a percentage point.",
              "type": "integer",
              "minimum": 50,
              "maximum": 2000,
              "default": 400
            }
          },
          {
            "name": "confidence",
            "in": "query",
            "required": false,
            "description": "How much of the resampled spread each interval should cover. A higher level separates fewer pairs, because it demands more evidence to call one project ahead of another.",
            "schema": {
              "description": "How much of the resampled spread each interval should cover. A higher level separates fewer pairs, because it demands more evidence to call one project ahead of another.",
              "type": "string",
              "enum": [
                "0.9",
                "0.95",
                "0.99"
              ],
              "default": "0.95"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Say which parts of the duel ranking the comparisons establish, and which are a tie.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "slug",
                        "name"
                      ]
                    },
                    "published": {
                      "type": "boolean"
                    },
                    "comparisonsDecided": {
                      "type": "integer"
                    },
                    "projects": {
                      "type": "integer",
                      "description": "Projects in the field the fit ranks."
                    },
                    "panelSize": {
                      "type": "integer",
                      "description": "Judges who decided at least one duel. The unit the resample draws from."
                    },
                    "resample": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "method": {
                          "type": "string"
                        },
                        "unit": {
                          "type": "string",
                          "enum": [
                            "judge",
                            "comparison"
                          ]
                        },
                        "unitRequested": {
                          "type": "string",
                          "enum": [
                            "judge",
                            "comparison"
                          ]
                        },
                        "seed": {
                          "type": "string",
                          "description": "Published so the intervals can be re-derived."
                        },
                        "confidence": {
                          "type": "number"
                        },
                        "replicates": {
                          "type": "integer"
                        },
                        "replicatesRequested": {
                          "type": "integer"
                        },
                        "replicatesConverged": {
                          "type": "integer"
                        },
                        "replicatesDisconnected": {
                          "type": "integer"
                        },
                        "resolution": {
                          "type": "number",
                          "description": "The finest share this many replicates resolve."
                        },
                        "threshold": {
                          "type": "number",
                          "description": "The share a reversal must stay under to be ordered."
                        },
                        "tiers": {
                          "type": "integer"
                        },
                        "unplaced": {
                          "type": "integer"
                        },
                        "decisive": {
                          "type": "boolean",
                          "description": "Whether first place is separated from second."
                        },
                        "orderAgreement": {
                          "type": "number"
                        },
                        "orderStability": {
                          "type": "number"
                        },
                        "projects": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "project": {
                                "type": "string"
                              },
                              "title": {
                                "type": "string"
                              },
                              "trackKey": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "rank": {
                                "type": "integer"
                              },
                              "beta": {
                                "type": "number"
                              },
                              "comparisons": {
                                "type": "integer"
                              },
                              "placed": {
                                "type": "boolean",
                                "description": "Whether any comparison mentions this project. When false every other number on the row describes where the middle of the field is, not where the project stands."
                              },
                              "standardError": {
                                "type": "number"
                              },
                              "low": {
                                "type": "number"
                              },
                              "high": {
                                "type": "number"
                              },
                              "rankMean": {
                                "type": "number"
                              },
                              "rankLow": {
                                "type": "integer"
                              },
                              "rankHigh": {
                                "type": "integer"
                              },
                              "rankStability": {
                                "type": "number"
                              },
                              "firstPlaceShare": {
                                "type": "number"
                              },
                              "tier": {
                                "type": "integer",
                                "description": "1-based, and 0 for a project no comparison mentions."
                              },
                              "sharesTier": {
                                "type": "integer",
                                "description": "How many other projects share its tier. Sharing a tier means not being separated from the project that opened it, which does not compose: read `pairs` for a boundary."
                              }
                            },
                            "required": [
                              "project",
                              "title",
                              "rank",
                              "beta",
                              "comparisons",
                              "placed",
                              "standardError",
                              "low",
                              "high",
                              "rankStability",
                              "tier",
                              "sharesTier"
                            ]
                          }
                        },
                        "pairs": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "above": {
                                "type": "string"
                              },
                              "aboveTitle": {
                                "type": "string"
                              },
                              "below": {
                                "type": "string"
                              },
                              "belowTitle": {
                                "type": "string"
                              },
                              "betaGap": {
                                "type": "number"
                              },
                              "reversalShare": {
                                "type": "number",
                                "description": "Share of resamples that put the lower project above the higher one."
                              },
                              "ordered": {
                                "type": "boolean",
                                "description": "Whether the evidence separates the pair at all."
                              }
                            },
                            "required": [
                              "above",
                              "aboveTitle",
                              "below",
                              "belowTitle",
                              "betaGap",
                              "reversalShare",
                              "ordered"
                            ]
                          }
                        },
                        "notes": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "code": {
                                "type": "string"
                              },
                              "severity": {
                                "type": "string",
                                "enum": [
                                  "info",
                                  "warn"
                                ]
                              },
                              "message": {
                                "type": "string"
                              },
                              "subjects": {
                                "type": "array",
                                "items": {
                                  "type": "string"
                                },
                                "description": "The ids the note is about, for a client that wants to highlight rows. Project ids stay ids here while the message names titles, because these are the machine-readable half; judge ids are replaced on both, on every public surface."
                              }
                            },
                            "required": [
                              "code",
                              "severity",
                              "message",
                              "subjects"
                            ]
                          }
                        }
                      },
                      "required": [
                        "method",
                        "unit",
                        "seed",
                        "confidence",
                        "replicates",
                        "resolution",
                        "threshold",
                        "tiers",
                        "unplaced",
                        "decisive",
                        "orderAgreement",
                        "projects",
                        "pairs",
                        "notes"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "event",
                    "published",
                    "comparisonsDecided",
                    "projects",
                    "panelSize",
                    "warnings"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.confidence",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        },
        "x-manak-limit": "analyse"
      }
    },
    "/api/events/{event}/results/publish": {
      "post": {
        "operationId": "results_publish",
        "summary": "Publish the ranking for everybody to read.",
        "description": "Callable by a organizer of the event.\n\nReversible: `results.unpublish` takes the page down again. The warnings on this response are the ones the public page carries, so publishing never looks cleaner than the ranking is.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "Private organizer note. Give a reason to publish a new revision after correcting evidence.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "publicSummary": {
                    "description": "Visible to everyone in result history. Keep judge and participant details private.",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 160
                  }
                },
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "description": "Private organizer note. Give a reason to publish a new revision after correcting evidence.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "publicSummary": {
                    "description": "Visible to everyone in result history. Keep judge and participant details private.",
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 160
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Publish the ranking for everybody to read.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "published": {
                      "type": "boolean"
                    },
                    "revision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "projects": {
                      "type": "integer"
                    },
                    "ballots": {
                      "type": "integer"
                    },
                    "comparisonsDecided": {
                      "type": "integer"
                    },
                    "converged": {
                      "type": "boolean"
                    },
                    "shortProjects": {
                      "type": "integer"
                    },
                    "tiers": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "decisive": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "reliability": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "published",
                    "changed",
                    "projects",
                    "warnings"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.publish",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "event.results_published",
          "result.published",
          "result.corrected"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/results/unpublish": {
      "post": {
        "operationId": "results_unpublish",
        "summary": "Take the published ranking back down.",
        "description": "Callable by a organizer of the event.\n\nThe ledger keeps the publication and the withdrawal, so a ranking that was briefly public cannot be made never to have happened.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Take the published ranking back down.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "published": {
                      "type": "boolean"
                    },
                    "revision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "changed": {
                      "type": "boolean"
                    },
                    "projects": {
                      "type": "integer"
                    },
                    "ballots": {
                      "type": "integer"
                    },
                    "comparisonsDecided": {
                      "type": "integer"
                    },
                    "converged": {
                      "type": "boolean"
                    },
                    "shortProjects": {
                      "type": "integer"
                    },
                    "tiers": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "decisive": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "reliability": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "published",
                    "changed",
                    "projects",
                    "warnings"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.unpublish",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "event.results_withdrawn"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/certificates": {
      "get": {
        "operationId": "results_certificates",
        "summary": "View issued Ed25519 verifiable certificates for this event.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only, read-only. Returns the stored signed snapshot, or an empty report before issuance. Never creates keys or signatures.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "View issued Ed25519 verifiable certificates for this event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "string"
                    },
                    "totalIssued": {
                      "type": "integer"
                    },
                    "participants": {
                      "type": "integer"
                    },
                    "judges": {
                      "type": "integer"
                    },
                    "winners": {
                      "type": "integer"
                    },
                    "publicKeyPem": {
                      "type": "string"
                    },
                    "issuerKeyId": {
                      "type": "string"
                    },
                    "publicationRevision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "publicationDigest": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "logoDataUrl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "certificates": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "event",
                    "totalIssued",
                    "participants",
                    "judges",
                    "winners",
                    "publicKeyPem",
                    "certificates"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.certificates",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "results_issue_certs",
        "summary": "Issue and sign Ed25519 certificates for participants, judges, and winners.",
        "description": "Callable by a organizer of the event.\n\nIssues cryptographic Ed25519 certificates. Refuses before results are published.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Issue and sign Ed25519 certificates for participants, judges, and winners.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "string"
                    },
                    "totalIssued": {
                      "type": "integer"
                    },
                    "participants": {
                      "type": "integer"
                    },
                    "judges": {
                      "type": "integer"
                    },
                    "winners": {
                      "type": "integer"
                    },
                    "publicKeyPem": {
                      "type": "string"
                    },
                    "certificates": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "event",
                    "totalIssued",
                    "participants",
                    "judges",
                    "winners",
                    "publicKeyPem",
                    "certificates"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.issue_certs",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "certificate.issued"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/certificates/studio": {
      "get": {
        "operationId": "results_certificate_studio",
        "summary": "Design certificates and view the issued recipient roster.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Design certificates and view the issued recipient roster.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "type": "string"
                    },
                    "eventSlug": {
                      "type": "string"
                    },
                    "totalIssued": {
                      "type": "integer"
                    },
                    "participants": {
                      "type": "integer"
                    },
                    "judges": {
                      "type": "integer"
                    },
                    "winners": {
                      "type": "integer"
                    },
                    "publicKeyPem": {
                      "type": "string"
                    },
                    "issuerKeyId": {
                      "type": "string"
                    },
                    "publicationRevision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "publicationDigest": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "logoDataUrl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "resultsPublic": {
                      "type": "boolean"
                    },
                    "template": {
                      "type": "object"
                    },
                    "certificates": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "event",
                    "eventSlug",
                    "template",
                    "certificates",
                    "totalIssued"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.certificate_studio",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/certificates/template": {
      "post": {
        "operationId": "results_configure_certificate_template",
        "summary": "Save the event certificate design before issuance.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "heading": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 90
                  },
                  "body": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 350
                  },
                  "footer": {
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 120
                  },
                  "signatory": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 100
                  }
                },
                "required": [
                  "heading",
                  "body",
                  "footer",
                  "signatory"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "heading": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 90
                  },
                  "body": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 350
                  },
                  "footer": {
                    "type": "string",
                    "minLength": 0,
                    "maxLength": 120
                  },
                  "signatory": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 100
                  }
                },
                "required": [
                  "heading",
                  "body",
                  "footer",
                  "signatory"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Save the event certificate design before issuance.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "presentation": {
                      "type": "object"
                    },
                    "logoDataUrl": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "presentation"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.configure_certificate_template",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "certificate.template.updated"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/certificates/{serial}": {
      "get": {
        "operationId": "results_public_certificate",
        "summary": "View an issued certificate and its current correction status.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "serial",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "View an issued certificate and its current correction status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "serial": {
                      "type": "string"
                    },
                    "eventName": {
                      "type": "string"
                    },
                    "recipientName": {
                      "type": "string"
                    },
                    "category": {
                      "type": "string"
                    },
                    "detail": {
                      "type": "string"
                    },
                    "issuedAt": {
                      "type": "integer"
                    },
                    "issuerOrigin": {
                      "type": "string"
                    },
                    "issuerKeyId": {
                      "type": "string"
                    },
                    "publicationRevision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "presentation": {
                      "type": "object"
                    },
                    "logoDataUrl": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string"
                    },
                    "correctionReason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "replacementSerial": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "eventSlug": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "serial",
                    "recipientName",
                    "status"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.public_certificate",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/certificates/status": {
      "get": {
        "operationId": "results_certificate_status",
        "summary": "Download signed certificate revocations and supersessions without recipient data.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Download signed certificate revocations and supersessions without recipient data.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "records": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "replacements": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "records"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.certificate_status",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/certificates/corrections": {
      "post": {
        "operationId": "results_correct_cert",
        "summary": "Sign a revocation or supersession for an issued certificate.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "serial": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 180
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "revoke",
                      "supersede"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  },
                  "recipientName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "recipientEmail": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "participation",
                      "judge",
                      "placement"
                    ]
                  },
                  "detail": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "required": [
                  "serial",
                  "action",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "serial": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 180
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "revoke",
                      "supersede"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  },
                  "recipientName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "recipientEmail": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254
                  },
                  "category": {
                    "type": "string",
                    "enum": [
                      "participation",
                      "judge",
                      "placement"
                    ]
                  },
                  "detail": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "required": [
                  "serial",
                  "action",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sign a revocation or supersession for an issued certificate.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "record": {
                      "type": "object"
                    },
                    "replacement": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "record"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.correct_cert",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "certificate.revoke",
          "certificate.supersede"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/results/history": {
      "get": {
        "operationId": "results_history",
        "summary": "List result publication revisions and correction reasons.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List result publication revisions and correction reasons.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revisions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "revisions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.history",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results/judge-evidence": {
      "post": {
        "operationId": "results_judge_evidence",
        "summary": "Exclude or restore one judge's evidence with an audited reason.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "exclude",
                      "include"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "judge",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "judge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "decision": {
                    "type": "string",
                    "enum": [
                      "exclude",
                      "include"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "judge",
                  "decision",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Exclude or restore one judge's evidence with an audited reason.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "judge": {
                      "type": "string"
                    },
                    "excluded": {
                      "type": "boolean"
                    },
                    "revision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "judge",
                    "excluded",
                    "revision"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.judge_evidence",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "judge.evidence_excluded",
          "judge.evidence_restored",
          "result.corrected"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/results/preflight": {
      "get": {
        "operationId": "results_preflight",
        "summary": "Check coverage, model warnings, and publication status before publishing.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Check coverage, model warnings, and publication status before publishing.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "ready": {
                      "type": "boolean"
                    },
                    "checks": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "evidenceDigest": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "revision",
                    "ready",
                    "checks",
                    "warnings",
                    "evidenceDigest"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.preflight",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results/evidence": {
      "get": {
        "operationId": "results_evidence_packet",
        "summary": "Download the public method and evidence summary bound to one result revision.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "results"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Download the public method and evidence summary bound to one result revision.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "issuedAt": {
                      "type": "integer"
                    },
                    "algorithm": {
                      "type": "string"
                    },
                    "options": {
                      "type": "object"
                    },
                    "rubricVersion": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "evidenceDigest": {
                      "type": "string"
                    },
                    "ledgerHead": {
                      "type": "string"
                    },
                    "ballots": {
                      "type": "integer"
                    },
                    "comparisonsDecided": {
                      "type": "integer"
                    },
                    "warnings": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "publicSummary": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "revision",
                    "issuedAt",
                    "algorithm",
                    "options",
                    "rubricVersion",
                    "evidenceDigest",
                    "ledgerHead",
                    "ballots",
                    "comparisonsDecided",
                    "warnings",
                    "publicSummary"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.evidence_packet",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results/explain": {
      "get": {
        "operationId": "results_explain",
        "summary": "Explain your team's frozen published ranking with anonymous review contributions.",
        "description": "Callable by a participant of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Explain your team's frozen published ranking with anonymous review contributions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": "integer"
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "notice": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "revision",
                    "projects",
                    "notice"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.explain",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/results/sandbox": {
      "get": {
        "operationId": "results_sandbox",
        "summary": "Compare normalization methods on current evidence without changing published results.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "results"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Compare normalization methods on current evidence without changing published results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "methods": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "notice": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "methods",
                    "notice"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "results.sandbox",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-limit": "analyse"
      }
    },
    "/api/events/{event}/awards": {
      "get": {
        "operationId": "awards_list",
        "summary": "List explicit award decisions for the current results revision.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "awards"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List explicit award decisions for the current results revision.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "decisions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "revision",
                    "decisions"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "awards.list",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "awards_decide",
        "summary": "Record an organizer award decision against the published revision.",
        "description": "Callable by a organizer of the event.\n\nRepeated award keys in one revision explicitly represent shared awards. A corrected publication requires new decisions.",
        "tags": [
          "awards"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "awardKey": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 80
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "placement",
                      "special"
                    ]
                  },
                  "place": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "publicSummary": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "project",
                  "awardKey",
                  "type",
                  "publicSummary",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "awardKey": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 80
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "placement",
                      "special"
                    ]
                  },
                  "place": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  },
                  "publicSummary": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "project",
                  "awardKey",
                  "type",
                  "publicSummary",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record an organizer award decision against the published revision.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "revision": {
                      "type": "integer"
                    },
                    "project": {
                      "type": "string"
                    },
                    "awardKey": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "revision",
                    "project",
                    "awardKey"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "awards.decide",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "award.decided"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/appeals": {
      "get": {
        "operationId": "appeals_list",
        "summary": "List public appeal resolutions, or private appeals you may inspect.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "appeals"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List public appeal resolutions, or private appeals you may inspect.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "appeals": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "appeals"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "appeals.list",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      },
      "post": {
        "operationId": "appeals_open",
        "summary": "Open a private appeal for your submitted team project.",
        "description": "Callable by a participant of the event.",
        "tags": [
          "appeals"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "privateMessage": {
                    "description": "Only organizers and you can read this text.",
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 2000
                  }
                },
                "required": [
                  "project",
                  "privateMessage"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "project": {
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "privateMessage": {
                    "description": "Only organizers and you can read this text.",
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 2000
                  }
                },
                "required": [
                  "project",
                  "privateMessage"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Open a private appeal for your submitted team project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    },
                    "deadlineAt": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "id",
                    "state",
                    "deadlineAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "appeals.open",
        "x-manak-capability": {
          "audience": "participant",
          "scope": "event"
        },
        "x-manak-records": [
          "appeal.opened"
        ],
        "x-manak-limit": "submission"
      }
    },
    "/api/events/{event}/appeals/{appeal}/resolve": {
      "post": {
        "operationId": "appeals_resolve",
        "summary": "Resolve an appeal and optionally publish a corrected result revision.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "appeals"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "appeal",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
              "minLength": 26,
              "maxLength": 26
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "accepted",
                      "rejected"
                    ]
                  },
                  "republish": {
                    "type": "boolean",
                    "default": false
                  },
                  "expectedRevision": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "publicSummary": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 300
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "decision",
                  "expectedRevision",
                  "publicSummary",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "accepted",
                      "rejected"
                    ]
                  },
                  "republish": {
                    "type": "boolean",
                    "default": false
                  },
                  "expectedRevision": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "publicSummary": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 300
                  },
                  "internalReason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "decision",
                  "expectedRevision",
                  "publicSummary",
                  "internalReason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resolve an appeal and optionally publish a corrected result revision.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    },
                    "correctionRevision": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "state",
                    "correctionRevision"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "appeals.resolve",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "appeal.resolved",
          "result.corrected"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/votes/start": {
      "post": {
        "operationId": "votes_start",
        "summary": "Start a voting session for this event.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "votes"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Start a voting session for this event.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "token": {
                      "type": "string",
                      "description": "The voter credential. Keep it private."
                    },
                    "credits": {
                      "type": "integer"
                    },
                    "expiresAt": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "token",
                    "credits",
                    "expiresAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.start",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        },
        "x-manak-records": [
          "voter.created"
        ],
        "x-manak-limit": "vote"
      }
    },
    "/api/events/{event}/votes": {
      "post": {
        "operationId": "votes_cast",
        "summary": "Spend voting credits on a submitted project.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "votes"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The token returned when voting started.",
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 43
                  },
                  "project": {
                    "description": "The project's identifier, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "influence": {
                    "description": "A vote of n influence costs n squared credits.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 1
                  }
                },
                "required": [
                  "project"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "description": "The token returned when voting started.",
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 43
                  },
                  "project": {
                    "description": "The project's identifier, as it appears in the URL.",
                    "type": "string",
                    "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$",
                    "minLength": 26,
                    "maxLength": 26
                  },
                  "influence": {
                    "description": "A vote of n influence costs n squared credits.",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10,
                    "default": 1
                  }
                },
                "required": [
                  "project"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Spend voting credits on a submitted project.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "project": {
                      "type": "string"
                    },
                    "influence": {
                      "type": "integer"
                    },
                    "credits": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "project",
                    "influence",
                    "credits"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.cast",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        },
        "x-manak-records": [
          "vote.cast"
        ],
        "x-manak-limit": "vote"
      },
      "get": {
        "operationId": "votes_results",
        "summary": "List the current public voting totals.",
        "description": "Callable by anyone, signed in or not.",
        "tags": [
          "votes"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the current public voting totals.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "votes": {
                            "type": "number"
                          },
                          "credits": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "project",
                          "votes",
                          "credits"
                        ]
                      }
                    }
                  },
                  "required": [
                    "projects"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.results",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/voting": {
      "get": {
        "operationId": "votes_ballot",
        "summary": "View your voting budget and shuffled project ballot.",
        "description": "Callable by anyone, signed in or not.\n\nUses the event-scoped HttpOnly cookie set by votes.start. API clients retain the Set-Cookie header. Projects are shuffled for that credential; only your own allocations are shown. No aggregate standings appear here.",
        "tags": [
          "votes"
        ],
        "security": [
          {}
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "View your voting budget and shuffled project ballot.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "mode": {
                      "type": "string"
                    },
                    "open": {
                      "type": "boolean"
                    },
                    "requiresSignIn": {
                      "type": "boolean"
                    },
                    "budget": {
                      "type": "integer"
                    },
                    "credits": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "summary": {
                            "type": "string"
                          },
                          "influence": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  },
                  "required": [
                    "mode",
                    "open",
                    "requiresSignIn",
                    "budget",
                    "credits",
                    "projects"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.ballot",
        "x-manak-capability": {
          "audience": "public",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/voting/abuse": {
      "get": {
        "operationId": "votes_abuse",
        "summary": "Detect and analyze suspicious voting rings and Sybil attacks.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only. Surfaces collusive voting rings, burst timings, and recommendation factors.",
        "tags": [
          "votes"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Detect and analyze suspicious voting rings and Sybil attacks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eventId": {
                      "type": "string"
                    },
                    "totalVotes": {
                      "type": "integer"
                    },
                    "uniqueVoters": {
                      "type": "integer"
                    },
                    "uniqueProjects": {
                      "type": "integer"
                    },
                    "highRiskCount": {
                      "type": "integer"
                    },
                    "policy": {
                      "type": "object"
                    },
                    "clusters": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "clusterId": {
                            "type": "integer"
                          },
                          "riskScore": {
                            "type": "number"
                          },
                          "voterTokens": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "targetProjects": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "sharedIpHash": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "timeSpanSeconds": {
                            "type": "number"
                          },
                          "primaryReason": {
                            "type": "string"
                          },
                          "details": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "recommendedDiscount": {
                            "type": "number"
                          },
                          "review": {
                            "type": [
                              "object",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "clusterId",
                          "riskScore",
                          "voterTokens",
                          "targetProjects",
                          "timeSpanSeconds",
                          "primaryReason",
                          "details",
                          "recommendedDiscount"
                        ]
                      }
                    }
                  },
                  "required": [
                    "eventId",
                    "totalVotes",
                    "uniqueVoters",
                    "uniqueProjects",
                    "highRiskCount",
                    "clusters"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.abuse",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/voting/abuse/policy": {
      "post": {
        "operationId": "votes_configure_abuse",
        "summary": "Set this event's voting anomaly thresholds.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "votes"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "patternPercent": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 100
                  },
                  "sharedOriginPercent": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 100
                  },
                  "highRisk": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  }
                },
                "required": [
                  "patternPercent",
                  "sharedOriginPercent",
                  "highRisk"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "patternPercent": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 100
                  },
                  "sharedOriginPercent": {
                    "type": "integer",
                    "minimum": 50,
                    "maximum": 100
                  },
                  "highRisk": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  }
                },
                "required": [
                  "patternPercent",
                  "sharedOriginPercent",
                  "highRisk"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Set this event's voting anomaly thresholds.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "patternCosine": {
                      "type": "number"
                    },
                    "sharedOriginCosine": {
                      "type": "number"
                    },
                    "highRisk": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "patternCosine",
                    "sharedOriginCosine",
                    "highRisk"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.configure_abuse",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "abuse.policy_updated"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/voting/abuse/review": {
      "post": {
        "operationId": "votes_review_abuse",
        "summary": "Record an investigator's assessment of one voting signal.",
        "description": "Callable by a organizer of the event.",
        "tags": [
          "votes"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "clusterTokens": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 4096
                  },
                  "state": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "benign",
                      "confirmed"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "clusterTokens",
                  "state",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "clusterTokens": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 4096
                  },
                  "state": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "benign",
                      "confirmed"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 1000
                  }
                },
                "required": [
                  "clusterTokens",
                  "state",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Record an investigator's assessment of one voting signal.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "signalKey": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "updatedAt": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "signalKey",
                    "state",
                    "reason",
                    "updatedAt"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.review_abuse",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "abuse.reviewed"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/voting/discount": {
      "post": {
        "operationId": "votes_discount_cluster",
        "summary": "Apply an audited discount after confirming a voting signal through human review.",
        "description": "Callable by a organizer of the event.\n\nRequires a confirmed review. Raw ballots are preserved; an audited factor is applied in aggregation.",
        "tags": [
          "votes"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "clusterTokens": {
                    "description": "Comma-separated list of voter hashes to discount.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  },
                  "discountPercent": {
                    "description": "Percentage to reduce ballot weights by (default 100% = nullify).",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 100
                  },
                  "reason": {
                    "description": "Reason for applying discount (logged permanently to audit trail).",
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 256
                  }
                },
                "required": [
                  "clusterTokens",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "clusterTokens": {
                    "description": "Comma-separated list of voter hashes to discount.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  },
                  "discountPercent": {
                    "description": "Percentage to reduce ballot weights by (default 100% = nullify).",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100,
                    "default": 100
                  },
                  "reason": {
                    "description": "Reason for applying discount (logged permanently to audit trail).",
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 256
                  }
                },
                "required": [
                  "clusterTokens",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Apply an audited discount after confirming a voting signal through human review.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "discountedVoters": {
                      "type": "integer"
                    },
                    "affectedVotes": {
                      "type": "integer"
                    },
                    "discountPercent": {
                      "type": "integer"
                    },
                    "reason": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "discountedVoters",
                    "affectedVotes",
                    "discountPercent",
                    "reason"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.discount_cluster",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "vote.cluster_discounted"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/voting/void": {
      "post": {
        "operationId": "votes_void_voter",
        "summary": "Void all votes cast by a suspicious voter identity.",
        "description": "Callable by a organizer of the event.\n\nNullifies voter weight to zero and logs permanent audit record.",
        "tags": [
          "votes"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The form encoding is the same operation and the same fields. It differs in one way: a URL-encoded body carries no types, so `3` and `true` arrive as text and are converted, while a JSON body of `\"3\"` for an integer is refused.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "voterToken": {
                    "description": "The token hash of the voter to void.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  },
                  "reason": {
                    "description": "Reason for voiding voter ballots.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 256
                  }
                },
                "required": [
                  "voterToken",
                  "reason"
                ],
                "additionalProperties": false
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "voterToken": {
                    "description": "The token hash of the voter to void.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  },
                  "reason": {
                    "description": "Reason for voiding voter ballots.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 256
                  }
                },
                "required": [
                  "voterToken",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Void all votes cast by a suspicious voter identity.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "voterToken": {
                      "type": "string"
                    },
                    "voided": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "ok",
                    "voterToken",
                    "voided",
                    "reason"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Well-formed, and refused: a deadline, a published rubric, a withdrawn project.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than this deployment accepts.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "Send `application/json` or `application/x-www-form-urlencoded`; nothing else is read.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "votes.void_voter",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        },
        "x-manak-records": [
          "vote.voter_voided"
        ],
        "x-manak-limit": "organize"
      }
    },
    "/api/events/{event}/csv/{stage}": {
      "get": {
        "operationId": "exports_download",
        "summary": "Download event records as CSV.",
        "description": "Callable by a organizer of the event.\n\nIncludes private event data. Requires the event organizer role for every stage, including results and projects. Use the JSONL archive for lossless backups; spreadsheet exports neutralize formula-like text.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          },
          {
            "name": "stage",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "registrations",
                "teams",
                "projects",
                "assignments",
                "ballots",
                "results",
                "votes",
                "audit"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.download",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/archive": {
      "get": {
        "operationId": "exports_archive_manifest",
        "summary": "Export the full lossless archive manifest and schema metadata.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only. Exposes archive structure and verified row counts across all strict tables.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Export the full lossless archive manifest and schema metadata.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "format": {
                      "type": "integer"
                    },
                    "head": {
                      "type": "string"
                    },
                    "tables": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "rows": {
                            "type": "integer"
                          }
                        },
                        "required": [
                          "name",
                          "rows"
                        ]
                      }
                    }
                  },
                  "required": [
                    "format",
                    "head",
                    "tables"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.archive_manifest",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/registrations.csv": {
      "get": {
        "operationId": "exports_registrations_csv",
        "summary": "Download registrations as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.registrations_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/teams.csv": {
      "get": {
        "operationId": "exports_teams_csv",
        "summary": "Download teams as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.teams_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/projects.csv": {
      "get": {
        "operationId": "exports_projects_csv",
        "summary": "Download projects as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.projects_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/scores.csv": {
      "get": {
        "operationId": "exports_scores_csv",
        "summary": "Download scores as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.scores_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/results.csv": {
      "get": {
        "operationId": "exports_results_csv",
        "summary": "Download results as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.results_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    },
    "/api/events/{event}/export/audit.csv": {
      "get": {
        "operationId": "exports_audit_csv",
        "summary": "Download audit as CSV.",
        "description": "Callable by a organizer of the event.\n\nOrganizer-only event data. Text cells are escaped against spreadsheet formulas. Use the JSONL archive for a lossless backup.",
        "tags": [
          "exports"
        ],
        "security": [
          {
            "session": []
          },
          {
            "bearer": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "The event's slug or id, as it appears in the URL.",
            "schema": {
              "description": "The event's slug or id, as it appears in the URL.",
              "type": "string",
              "minLength": 2,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Organizer-only CSV download.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request itself could not be read: a bad escape in the URL, or a body that is not the JSON it claims to be.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Nobody is signed in. Sign in and retry.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Signed in, and a member of this event, but not with the role this needs.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such thing — or none that this caller is allowed to know exists.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "The submission is malformed. Every problem is listed, not just the first.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. `Retry-After` says how long, and the window is fixed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds."
              }
            }
          },
          "500": {
            "description": "A bug. The operator's log has the details; this response does not.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "x-manak-command": "exports.audit_csv",
        "x-manak-capability": {
          "audience": "organizer",
          "scope": "event"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "A refusal, in the shape RFC 9457 describes. `code` is the stable machine-readable name; `detail` is this occurrence and may be shown to a person.",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference for the problem type."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "examples": [
              "project.missing"
            ]
          },
          "problems": {
            "type": "array",
            "description": "Present on a 422: every field that needs attention, not just one.",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "field",
                "message"
              ],
              "additionalProperties": false
            }
          },
          "meta": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "session": {
        "type": "apiKey",
        "in": "cookie",
        "name": "manak_session",
        "description": "The cookie a browser gets from a sign-in link. Set `HttpOnly`, `SameSite=Lax` and — where the deployment is served over TLS — `Secure`."
      },
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "The same session token as the cookie, for clients that are not browsers. One credential kind, so revoking a session revokes both."
      }
    }
  }
}
