{
  "openapi": "3.0.3",
  "info": {
    "title": "Release Harbor API",
    "version": "1.0.0",
    "description": "Public distribution API and authenticated publishing API. All JSON responses use {ok,data} or {ok:false,error}. Latest means last published in channel. All listed resources are public. PHP + SQLite edition. No reverse proxy or Python application server required."
  },
  "servers": [
    {
      "url": "https://new.huohh.cn",
      "description": "Baota production domain; deployment required"
    },
    {
      "url": "/",
      "description": "Current origin for local preview or alternate deployment"
    }
  ],
  "paths": {
    "/api/v1/status": {
      "get": {
        "summary": "Installation status",
        "operationId": "get__api_v1_status",
        "description": "",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "runtime": {
                          "type": "string",
                          "enum": [
                            "php"
                          ]
                        },
                        "initialized": {
                          "type": "boolean"
                        },
                        "setup_mode": {
                          "type": "string",
                          "enum": [
                            "key-web"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        }
      }
    },
    "/api/v1/setup": {
      "post": {
        "summary": "Initialize locally",
        "operationId": "post__api_v1_setup",
        "description": "One-time web setup. Requires private storage/install.key. Cannot reset an existing installation.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Token"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "setup_key",
                  "password"
                ],
                "properties": {
                  "password": {
                    "type": "string",
                    "minLength": 12,
                    "maxLength": 72,
                    "description": "12+ Unicode characters and at most 72 UTF-8 bytes"
                  },
                  "setup_key": {
                    "type": "string",
                    "description": "Private one-time key, never obtainable from public API"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/login": {
      "post": {
        "summary": "Admin login",
        "operationId": "post__api_v1_login",
        "description": "Admin session expires in 8 hours. Password verified with PHP password_verify.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Token"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "password"
                ],
                "properties": {
                  "password": {
                    "type": "string",
                    "minLength": 12,
                    "maxLength": 256
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/logout": {
      "post": {
        "summary": "Revoke current session or token",
        "operationId": "post__api_v1_logout",
        "description": "",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/products": {
      "get": {
        "summary": "List software and services",
        "operationId": "get__api_v1_products",
        "description": "",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        }
      }
    },
    "/api/v1/products/{slug}": {
      "get": {
        "summary": "Get product",
        "operationId": "get__api_v1_products_slug",
        "description": "",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/products/{slug}/latest": {
      "get": {
        "summary": "Latest release",
        "operationId": "get__api_v1_products_slug_latest",
        "description": "Order by publication ID descending, not semantic version. 404 if no latest release.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Release"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "stable"
            }
          }
        ]
      }
    },
    "/api/v1/products/{slug}/releases": {
      "get": {
        "summary": "Release history (max 200)",
        "operationId": "get__api_v1_products_slug_releases",
        "description": "Order by publication ID descending, not semantic version. 404 if no latest release.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Release"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "stable"
            }
          }
        ]
      }
    },
    "/api/v1/announcements": {
      "get": {
        "summary": "List announcements (max 200)",
        "operationId": "get__api_v1_announcements",
        "description": "Product filter includes site-wide notices.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Announcement"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "product",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/v1/resources": {
      "get": {
        "summary": "Search standalone public files and links",
        "operationId": "get__api_v1_resources",
        "description": "limit 1..200; category exact match; q substring search; offset pagination.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Resource"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ]
      }
    },
    "/api/v1/admin/products": {
      "post": {
        "summary": "Publish products",
        "operationId": "post__api_v1_admin_products",
        "description": "publish or admin scope. Products are upserted; other items are newly created.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Product"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/announcements": {
      "post": {
        "summary": "Publish announcements",
        "operationId": "post__api_v1_admin_announcements",
        "description": "publish or admin scope. Products are upserted; other items are newly created.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AnnouncementInput"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/releases": {
      "post": {
        "summary": "Publish releases",
        "operationId": "post__api_v1_admin_releases",
        "description": "publish or admin scope. Products are upserted; other items are newly created.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Release"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReleaseInput"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/resources": {
      "post": {
        "summary": "Publish resources",
        "operationId": "post__api_v1_admin_resources",
        "description": "publish or admin scope. Products are upserted; other items are newly created.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResourceInput"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/announcements/{id}": {
      "delete": {
        "summary": "Unpublish / revoke announcements",
        "operationId": "delete__api_v1_admin_announcements_id",
        "description": "tokens requires admin. File bytes are retained; unreferenced files cannot be downloaded.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/releases/{id}": {
      "delete": {
        "summary": "Unpublish / revoke releases",
        "operationId": "delete__api_v1_admin_releases_id",
        "description": "tokens requires admin. File bytes are retained; unreferenced files cannot be downloaded.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/resources/{id}": {
      "delete": {
        "summary": "Unpublish / revoke resources",
        "operationId": "delete__api_v1_admin_resources_id",
        "description": "tokens requires admin. File bytes are retained; unreferenced files cannot be downloaded.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/tokens/{id}": {
      "delete": {
        "summary": "Unpublish / revoke tokens",
        "operationId": "delete__api_v1_admin_tokens_id",
        "description": "tokens requires admin. File bytes are retained; unreferenced files cannot be downloaded.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/tokens": {
      "get": {
        "summary": "List publisher credentials without secret hashes",
        "operationId": "get__api_v1_admin_tokens",
        "description": "Admin only. No raw token returned.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Token"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "summary": "Create publish-scoped credential",
        "operationId": "post__api_v1_admin_tokens",
        "description": "Admin only. Raw token shown once; no automatic expiry; revoke manually.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Token"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/password": {
      "post": {
        "summary": "Change admin password and invalidate admin sessions",
        "operationId": "post__api_v1_admin_password",
        "description": "Admin only. Publishing tokens remain valid.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "password"
                ],
                "properties": {
                  "password": {
                    "type": "string",
                    "minLength": 12,
                    "maxLength": 72,
                    "description": "12+ characters, max 72 UTF-8 bytes"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/audit": {
      "get": {
        "summary": "Read last 100 authorized mutations",
        "operationId": "get__api_v1_admin_audit",
        "description": "Admin only. Credentials and request bodies are not logged.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/api/v1/admin/files": {
      "post": {
        "summary": "Stream arbitrary file upload",
        "operationId": "post__api_v1_admin_files",
        "description": "Raw binary, not multipart. Content-Length required. Default max 512 MiB. Uploaded files are private until referenced by a published resource or release.",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "data"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/File"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Invalid credentials"
          },
          "403": {
            "description": "Insufficient scope"
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Duplicate version or invalid reference"
          },
          "413": {
            "description": "Upload too large"
          },
          "429": {
            "description": "Login rate limited"
          }
        },
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      }
    },
    "/downloads/{file_id}": {
      "get": {
        "summary": "Download published file",
        "operationId": "downloadFile",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Single byte range"
          },
          "404": {
            "description": "Not published"
          },
          "416": {
            "description": "Invalid range"
          }
        }
      },
      "head": {
        "summary": "File headers",
        "operationId": "headFile",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Content-Length, ETag, Accept-Ranges"
          },
          "404": {
            "description": "Not published"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "schemas": {
      "Product": {
        "type": "object",
        "required": [
          "slug",
          "name",
          "kind"
        ],
        "properties": {
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "maxLength": 80
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "kind": {
            "type": "string",
            "enum": [
              "software",
              "service"
            ]
          },
          "description": {
            "type": "string",
            "maxLength": 4000
          },
          "homepage": {
            "type": "string",
            "description": "Empty or HTTP(S) URL"
          }
        }
      },
      "Asset": {
        "type": "object",
        "required": [
          "name",
          "platform",
          "kind"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "example": "windows-x64"
          },
          "kind": {
            "type": "string",
            "enum": [
              "file",
              "link",
              "code"
            ]
          },
          "file_id": {
            "type": "string",
            "description": "Required for file; ID from upload response"
          },
          "url": {
            "type": "string",
            "description": "HTTP(S), required for link; relative download URL in response"
          },
          "code": {
            "type": "string",
            "description": "Required for code"
          },
          "size": {
            "type": "integer",
            "nullable": true
          },
          "sha256": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ReleaseInput": {
        "type": "object",
        "required": [
          "product",
          "version",
          "channel"
        ],
        "properties": {
          "product": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "pattern": "^[a-z0-9-]+$",
            "example": "stable"
          },
          "notes": {
            "type": "string"
          },
          "assets": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/Asset"
            }
          }
        }
      },
      "Release": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ReleaseInput"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "created_at": {
                "type": "integer",
                "description": "Unix seconds"
              }
            }
          }
        ]
      },
      "AnnouncementInput": {
        "type": "object",
        "required": [
          "title",
          "body"
        ],
        "properties": {
          "title": {
            "type": "string"
          },
          "body": {
            "type": "string"
          },
          "product": {
            "type": "string",
            "description": "Empty or omitted = site-wide"
          }
        }
      },
      "Announcement": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AnnouncementInput"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "created_at": {
                "type": "integer"
              },
              "product": {
                "type": "string",
                "nullable": true
              }
            }
          }
        ]
      },
      "ResourceInput": {
        "type": "object",
        "required": [
          "name",
          "category"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "HTTP(S). Exactly one of file_id/url must be supplied"
          }
        }
      },
      "Resource": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ResourceInput"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "created_at": {
                "type": "integer"
              },
              "filename": {
                "type": "string",
                "nullable": true
              },
              "size": {
                "type": "integer",
                "nullable": true
              },
              "sha256": {
                "type": "string",
                "nullable": true
              }
            }
          }
        ]
      },
      "File": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "sha256": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "Token": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "token": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "expires_at": {
            "type": "integer"
          }
        }
      }
    }
  }
}