{
  "openapi": "3.1.0",
  "info": {
    "title": "Token Registry",
    "version": "1.0.0",
    "description": "Authenticated registry for one-time device token claims."
  },
  "servers": [
    {
      "url": "/",
      "description": "Current host"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Service health checks"
    },
    {
      "name": "Public",
      "description": "Device enrollment endpoints"
    },
    {
      "name": "Admin",
      "description": "Authenticated registry management"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Docs landing page",
        "responses": {
          "200": {
            "description": "HTML documentation"
          }
        }
      }
    },
    "/docs": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Documentation page",
        "responses": {
          "200": {
            "description": "HTML documentation"
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "OpenAPI document",
        "responses": {
          "200": {
            "description": "OpenAPI JSON document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Health check",
        "responses": {
          "200": {
            "description": "Service is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tunnels/claim": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Claim a tunnel token for a device serial",
        "description": "The device submits its serial number and an HMAC-SHA256 proof derived from BOOTSTRAP_TOKEN.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClaimRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Claim succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClaimResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid request fields"
          },
          "401": {
            "description": "Bootstrap proof did not validate"
          },
          "404": {
            "description": "Serial not found"
          },
          "409": {
            "description": "Serial already claimed"
          },
          "503": {
            "description": "Bootstrap token is not configured"
          }
        }
      }
    },
    "/v1/tunnels": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List tunnel records",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tunnel records",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TunnelListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Admin token missing or invalid"
          }
        }
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create or update a tunnel record",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TunnelUpsertRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tunnel record saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TunnelResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid JSON or missing fields"
          },
          "401": {
            "description": "Admin token missing or invalid"
          }
        }
      }
    },
    "/v1/tunnels/{serial}": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get a tunnel record by serial",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "serial",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tunnel record",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TunnelResponse"
                }
              }
            }
          },
          "401": {
            "description": "Admin token missing or invalid"
          },
          "404": {
            "description": "Serial not found"
          }
        }
      },
      "delete": {
        "tags": [
          "Admin"
        ],
        "summary": "Delete a tunnel record by serial",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "serial",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tunnel deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Admin token missing or invalid"
          },
          "404": {
            "description": "Serial not found"
          }
        }
      }
    },
    "/v1/tunnels/{serial}/claim": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Mark a tunnel as claimed",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "serial",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tunnel marked as claimed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TunnelResponse"
                }
              }
            }
          },
          "401": {
            "description": "Admin token missing or invalid"
          },
          "404": {
            "description": "Serial not found"
          }
        }
      }
    },
    "/v1/tunnels/{serial}/reset-claim": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Clear a tunnel claim",
        "security": [
          {
            "AdminToken": []
          }
        ],
        "parameters": [
          {
            "name": "serial",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tunnel claim cleared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TunnelResponse"
                }
              }
            }
          },
          "401": {
            "description": "Admin token missing or invalid"
          },
          "404": {
            "description": "Serial not found"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "AdminToken": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Use `Authorization: Bearer <ADMIN_TOKEN>` or `X-Admin-Token: <ADMIN_TOKEN>`."
      }
    },
    "schemas": {
      "HealthResponse": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "examples": [
              "ok"
            ]
          }
        }
      },
      "ClaimRequest": {
        "type": "object",
        "required": [
          "serial",
          "bootstrap_proof"
        ],
        "properties": {
          "serial": {
            "type": "string",
            "example": "ABC123"
          },
          "bootstrap_proof": {
            "type": "string",
            "description": "HMAC-SHA256 hex digest of the serial using BOOTSTRAP_TOKEN as the secret.",
            "example": "3f0f6f91d4f6f0cb1e8b88a0cc1c2dcd9e5fefb8b532d2a09bcf8d3cf93ce2a1"
          }
        }
      },
      "ClaimResponse": {
        "type": "object",
        "required": [
          "serial",
          "tunnel_name",
          "token",
          "claimed_at"
        ],
        "properties": {
          "serial": {
            "type": "string"
          },
          "tunnel_name": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "claimed_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TunnelRecord": {
        "type": "object",
        "required": [
          "serial",
          "tunnel_name",
          "token",
          "notes",
          "claimed_at",
          "updated_at"
        ],
        "properties": {
          "serial": {
            "type": "string"
          },
          "tunnel_name": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "claimed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TunnelListResponse": {
        "type": "object",
        "required": [
          "tunnels"
        ],
        "properties": {
          "tunnels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TunnelRecord"
            }
          }
        }
      },
      "TunnelResponse": {
        "type": "object",
        "required": [
          "tunnel"
        ],
        "properties": {
          "tunnel": {
            "$ref": "#/components/schemas/TunnelRecord"
          }
        }
      },
      "TunnelUpsertRequest": {
        "type": "object",
        "required": [
          "serial",
          "tunnel_name",
          "token"
        ],
        "properties": {
          "serial": {
            "type": "string"
          },
          "tunnel_name": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "DeleteResponse": {
        "type": "object",
        "required": [
          "deleted"
        ],
        "properties": {
          "deleted": {
            "type": "string"
          }
        }
      }
    }
  }
}
