Update api docs

This commit is contained in:
2025-12-03 21:25:03 +01:00
parent 5ccf493e04
commit 85cf712b03
6 changed files with 1136 additions and 56 deletions

View File

@@ -19,6 +19,235 @@ const docTemplate = `{
"host": "{{.Host}}", "host": "{{.Host}}",
"basePath": "{{.BasePath}}", "basePath": "{{.BasePath}}",
"paths": { "paths": {
"/api/v1/auth/keys": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns a list of all API keys for the system user (excludes key hash and plain-text key)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "List all API keys",
"responses": {
"200": {
"description": "List of API keys",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/server.KeyResponse"
}
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
},
"post": {
"description": "Creates a new API key with the specified permissions and returns the plain-text key (only shown once)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Create a new API key",
"parameters": [
{
"description": "API key configuration",
"name": "key",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/server.CreateKeyRequest"
}
}
],
"responses": {
"201": {
"description": "Created API key with plain-text key",
"schema": {
"$ref": "#/definitions/server.CreateKeyResponse"
}
},
"400": {
"description": "Invalid request body or validation error",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/auth/keys/{id}": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns details for a specific API key by ID (excludes key hash and plain-text key)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Get details of a specific API key",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "API key details",
"schema": {
"$ref": "#/definitions/server.KeyResponse"
}
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
},
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Deletes an API key by ID",
"tags": [
"Keys"
],
"summary": "Delete an API key",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "API key deleted successfully"
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/auth/keys/{id}/permissions": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the instance-level permissions for a specific API key (includes instance names)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Get API key permissions",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "List of key permissions",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/server.KeyPermissionResponse"
}
}
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/backends/llama-cpp/devices": { "/api/v1/backends/llama-cpp/devices": {
"get": { "get": {
"security": [ "security": [
@@ -1503,6 +1732,17 @@ const docTemplate = `{
} }
}, },
"definitions": { "definitions": {
"auth.PermissionMode": {
"type": "string",
"enum": [
"allow_all",
"per_instance"
],
"x-enum-varnames": [
"PermissionModeAllowAll",
"PermissionModePerInstance"
]
},
"config.AppConfig": { "config.AppConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1518,6 +1758,13 @@ const docTemplate = `{
"commit_hash": { "commit_hash": {
"type": "string" "type": "string"
}, },
"data_dir": {
"description": "Directory where all llamactl data will be stored (database, instances, logs, etc.)",
"type": "string"
},
"database": {
"$ref": "#/definitions/config.DatabaseConfig"
},
"instances": { "instances": {
"$ref": "#/definitions/config.InstancesConfig" "$ref": "#/definitions/config.InstancesConfig"
}, },
@@ -1608,6 +1855,26 @@ const docTemplate = `{
} }
} }
}, },
"config.DatabaseConfig": {
"type": "object",
"properties": {
"connection_max_lifetime": {
"type": "string",
"example": "1h"
},
"max_idle_connections": {
"type": "integer"
},
"max_open_connections": {
"description": "Connection settings",
"type": "integer"
},
"path": {
"description": "Database file path (relative to the top-level data_dir or absolute)",
"type": "string"
}
}
},
"config.DockerSettings": { "config.DockerSettings": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1639,11 +1906,7 @@ const docTemplate = `{
"type": "boolean" "type": "boolean"
}, },
"configs_dir": { "configs_dir": {
"description": "Instance config directory override", "description": "Instance config directory override (relative to data_dir if not absolute)",
"type": "string"
},
"data_dir": {
"description": "Directory where all llamactl data will be stored (instances.json, logs, etc.)",
"type": "string" "type": "string"
}, },
"default_auto_restart": { "default_auto_restart": {
@@ -1667,7 +1930,7 @@ const docTemplate = `{
"type": "boolean" "type": "boolean"
}, },
"logs_dir": { "logs_dir": {
"description": "Logs directory override", "description": "Logs directory override (relative to data_dir if not absolute)",
"type": "string" "type": "string"
}, },
"max_instances": { "max_instances": {
@@ -1748,7 +2011,10 @@ const docTemplate = `{
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
"description": "Unix timestamp when the instance was created", "description": "Unix timestamp when instance was created",
"type": "integer"
},
"id": {
"type": "integer" "type": "integer"
}, },
"name": { "name": {
@@ -1794,6 +2060,125 @@ const docTemplate = `{
} }
} }
}, },
"server.CreateKeyRequest": {
"type": "object",
"properties": {
"expiresAt": {
"type": "integer",
"format": "int64"
},
"instancePermissions": {
"type": "array",
"items": {
"$ref": "#/definitions/server.InstancePermission"
}
},
"name": {
"type": "string"
},
"permissionMode": {
"$ref": "#/definitions/auth.PermissionMode"
}
}
},
"server.CreateKeyResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "integer"
},
"enabled": {
"type": "boolean"
},
"expires_at": {
"type": "integer"
},
"id": {
"type": "integer"
},
"key": {
"type": "string"
},
"last_used_at": {
"type": "integer"
},
"name": {
"type": "string"
},
"permission_mode": {
"$ref": "#/definitions/auth.PermissionMode"
},
"updated_at": {
"type": "integer"
},
"user_id": {
"type": "string"
}
}
},
"server.InstancePermission": {
"type": "object",
"properties": {
"can_infer": {
"type": "boolean"
},
"can_view_logs": {
"type": "boolean"
},
"instance_id": {
"type": "integer"
}
}
},
"server.KeyPermissionResponse": {
"type": "object",
"properties": {
"can_infer": {
"type": "boolean"
},
"can_view_logs": {
"type": "boolean"
},
"instance_id": {
"type": "integer"
},
"instance_name": {
"type": "string"
}
}
},
"server.KeyResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "integer"
},
"enabled": {
"type": "boolean"
},
"expires_at": {
"type": "integer"
},
"id": {
"type": "integer"
},
"last_used_at": {
"type": "integer"
},
"name": {
"type": "string"
},
"permission_mode": {
"$ref": "#/definitions/auth.PermissionMode"
},
"updated_at": {
"type": "integer"
},
"user_id": {
"type": "string"
}
}
},
"server.NodeResponse": { "server.NodeResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -12,6 +12,235 @@
}, },
"basePath": "/api/v1", "basePath": "/api/v1",
"paths": { "paths": {
"/api/v1/auth/keys": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns a list of all API keys for the system user (excludes key hash and plain-text key)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "List all API keys",
"responses": {
"200": {
"description": "List of API keys",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/server.KeyResponse"
}
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
},
"post": {
"description": "Creates a new API key with the specified permissions and returns the plain-text key (only shown once)",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Create a new API key",
"parameters": [
{
"description": "API key configuration",
"name": "key",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/server.CreateKeyRequest"
}
}
],
"responses": {
"201": {
"description": "Created API key with plain-text key",
"schema": {
"$ref": "#/definitions/server.CreateKeyResponse"
}
},
"400": {
"description": "Invalid request body or validation error",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/auth/keys/{id}": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns details for a specific API key by ID (excludes key hash and plain-text key)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Get details of a specific API key",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "API key details",
"schema": {
"$ref": "#/definitions/server.KeyResponse"
}
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
},
"delete": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Deletes an API key by ID",
"tags": [
"Keys"
],
"summary": "Delete an API key",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "API key deleted successfully"
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/auth/keys/{id}/permissions": {
"get": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "Returns the instance-level permissions for a specific API key (includes instance names)",
"produces": [
"application/json"
],
"tags": [
"Keys"
],
"summary": "Get API key permissions",
"parameters": [
{
"type": "integer",
"description": "Key ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "List of key permissions",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/server.KeyPermissionResponse"
}
}
},
"400": {
"description": "Invalid key ID",
"schema": {
"type": "string"
}
},
"404": {
"description": "API key not found",
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "string"
}
}
}
}
},
"/api/v1/backends/llama-cpp/devices": { "/api/v1/backends/llama-cpp/devices": {
"get": { "get": {
"security": [ "security": [
@@ -1496,6 +1725,17 @@
} }
}, },
"definitions": { "definitions": {
"auth.PermissionMode": {
"type": "string",
"enum": [
"allow_all",
"per_instance"
],
"x-enum-varnames": [
"PermissionModeAllowAll",
"PermissionModePerInstance"
]
},
"config.AppConfig": { "config.AppConfig": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1511,6 +1751,13 @@
"commit_hash": { "commit_hash": {
"type": "string" "type": "string"
}, },
"data_dir": {
"description": "Directory where all llamactl data will be stored (database, instances, logs, etc.)",
"type": "string"
},
"database": {
"$ref": "#/definitions/config.DatabaseConfig"
},
"instances": { "instances": {
"$ref": "#/definitions/config.InstancesConfig" "$ref": "#/definitions/config.InstancesConfig"
}, },
@@ -1601,6 +1848,26 @@
} }
} }
}, },
"config.DatabaseConfig": {
"type": "object",
"properties": {
"connection_max_lifetime": {
"type": "string",
"example": "1h"
},
"max_idle_connections": {
"type": "integer"
},
"max_open_connections": {
"description": "Connection settings",
"type": "integer"
},
"path": {
"description": "Database file path (relative to the top-level data_dir or absolute)",
"type": "string"
}
}
},
"config.DockerSettings": { "config.DockerSettings": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -1632,11 +1899,7 @@
"type": "boolean" "type": "boolean"
}, },
"configs_dir": { "configs_dir": {
"description": "Instance config directory override", "description": "Instance config directory override (relative to data_dir if not absolute)",
"type": "string"
},
"data_dir": {
"description": "Directory where all llamactl data will be stored (instances.json, logs, etc.)",
"type": "string" "type": "string"
}, },
"default_auto_restart": { "default_auto_restart": {
@@ -1660,7 +1923,7 @@
"type": "boolean" "type": "boolean"
}, },
"logs_dir": { "logs_dir": {
"description": "Logs directory override", "description": "Logs directory override (relative to data_dir if not absolute)",
"type": "string" "type": "string"
}, },
"max_instances": { "max_instances": {
@@ -1741,7 +2004,10 @@
"type": "object", "type": "object",
"properties": { "properties": {
"created": { "created": {
"description": "Unix timestamp when the instance was created", "description": "Unix timestamp when instance was created",
"type": "integer"
},
"id": {
"type": "integer" "type": "integer"
}, },
"name": { "name": {
@@ -1787,6 +2053,125 @@
} }
} }
}, },
"server.CreateKeyRequest": {
"type": "object",
"properties": {
"expiresAt": {
"type": "integer",
"format": "int64"
},
"instancePermissions": {
"type": "array",
"items": {
"$ref": "#/definitions/server.InstancePermission"
}
},
"name": {
"type": "string"
},
"permissionMode": {
"$ref": "#/definitions/auth.PermissionMode"
}
}
},
"server.CreateKeyResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "integer"
},
"enabled": {
"type": "boolean"
},
"expires_at": {
"type": "integer"
},
"id": {
"type": "integer"
},
"key": {
"type": "string"
},
"last_used_at": {
"type": "integer"
},
"name": {
"type": "string"
},
"permission_mode": {
"$ref": "#/definitions/auth.PermissionMode"
},
"updated_at": {
"type": "integer"
},
"user_id": {
"type": "string"
}
}
},
"server.InstancePermission": {
"type": "object",
"properties": {
"can_infer": {
"type": "boolean"
},
"can_view_logs": {
"type": "boolean"
},
"instance_id": {
"type": "integer"
}
}
},
"server.KeyPermissionResponse": {
"type": "object",
"properties": {
"can_infer": {
"type": "boolean"
},
"can_view_logs": {
"type": "boolean"
},
"instance_id": {
"type": "integer"
},
"instance_name": {
"type": "string"
}
}
},
"server.KeyResponse": {
"type": "object",
"properties": {
"created_at": {
"type": "integer"
},
"enabled": {
"type": "boolean"
},
"expires_at": {
"type": "integer"
},
"id": {
"type": "integer"
},
"last_used_at": {
"type": "integer"
},
"name": {
"type": "string"
},
"permission_mode": {
"$ref": "#/definitions/auth.PermissionMode"
},
"updated_at": {
"type": "integer"
},
"user_id": {
"type": "string"
}
}
},
"server.NodeResponse": { "server.NodeResponse": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@@ -1,5 +1,13 @@
basePath: /api/v1 basePath: /api/v1
definitions: definitions:
auth.PermissionMode:
enum:
- allow_all
- per_instance
type: string
x-enum-varnames:
- PermissionModeAllowAll
- PermissionModePerInstance
config.AppConfig: config.AppConfig:
properties: properties:
auth: auth:
@@ -10,6 +18,12 @@ definitions:
type: string type: string
commit_hash: commit_hash:
type: string type: string
data_dir:
description: Directory where all llamactl data will be stored (database, instances,
logs, etc.)
type: string
database:
$ref: '#/definitions/config.DatabaseConfig'
instances: instances:
$ref: '#/definitions/config.InstancesConfig' $ref: '#/definitions/config.InstancesConfig'
local_node: local_node:
@@ -70,6 +84,20 @@ definitions:
type: string type: string
type: object type: object
type: object type: object
config.DatabaseConfig:
properties:
connection_max_lifetime:
example: 1h
type: string
max_idle_connections:
type: integer
max_open_connections:
description: Connection settings
type: integer
path:
description: Database file path (relative to the top-level data_dir or absolute)
type: string
type: object
config.DockerSettings: config.DockerSettings:
properties: properties:
args: args:
@@ -91,11 +119,8 @@ definitions:
description: Automatically create the data directory if it doesn't exist description: Automatically create the data directory if it doesn't exist
type: boolean type: boolean
configs_dir: configs_dir:
description: Instance config directory override description: Instance config directory override (relative to data_dir if not
type: string absolute)
data_dir:
description: Directory where all llamactl data will be stored (instances.json,
logs, etc.)
type: string type: string
default_auto_restart: default_auto_restart:
description: Default auto-restart setting for new instances description: Default auto-restart setting for new instances
@@ -113,7 +138,7 @@ definitions:
description: Enable LRU eviction for instance logs description: Enable LRU eviction for instance logs
type: boolean type: boolean
logs_dir: logs_dir:
description: Logs directory override description: Logs directory override (relative to data_dir if not absolute)
type: string type: string
max_instances: max_instances:
description: Maximum number of instances that can be created description: Maximum number of instances that can be created
@@ -171,7 +196,9 @@ definitions:
instance.Instance: instance.Instance:
properties: properties:
created: created:
description: Unix timestamp when the instance was created description: Unix timestamp when instance was created
type: integer
id:
type: integer type: integer
name: name:
type: string type: string
@@ -203,6 +230,84 @@ definitions:
description: seconds description: seconds
type: integer type: integer
type: object type: object
server.CreateKeyRequest:
properties:
expiresAt:
format: int64
type: integer
instancePermissions:
items:
$ref: '#/definitions/server.InstancePermission'
type: array
name:
type: string
permissionMode:
$ref: '#/definitions/auth.PermissionMode'
type: object
server.CreateKeyResponse:
properties:
created_at:
type: integer
enabled:
type: boolean
expires_at:
type: integer
id:
type: integer
key:
type: string
last_used_at:
type: integer
name:
type: string
permission_mode:
$ref: '#/definitions/auth.PermissionMode'
updated_at:
type: integer
user_id:
type: string
type: object
server.InstancePermission:
properties:
can_infer:
type: boolean
can_view_logs:
type: boolean
instance_id:
type: integer
type: object
server.KeyPermissionResponse:
properties:
can_infer:
type: boolean
can_view_logs:
type: boolean
instance_id:
type: integer
instance_name:
type: string
type: object
server.KeyResponse:
properties:
created_at:
type: integer
enabled:
type: boolean
expires_at:
type: integer
id:
type: integer
last_used_at:
type: integer
name:
type: string
permission_mode:
$ref: '#/definitions/auth.PermissionMode'
updated_at:
type: integer
user_id:
type: string
type: object
server.NodeResponse: server.NodeResponse:
properties: properties:
address: address:
@@ -242,6 +347,156 @@ info:
title: llamactl API title: llamactl API
version: "1.0" version: "1.0"
paths: paths:
/api/v1/auth/keys:
get:
description: Returns a list of all API keys for the system user (excludes key
hash and plain-text key)
produces:
- application/json
responses:
"200":
description: List of API keys
schema:
items:
$ref: '#/definitions/server.KeyResponse'
type: array
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: List all API keys
tags:
- Keys
post:
consumes:
- application/json
description: Creates a new API key with the specified permissions and returns
the plain-text key (only shown once)
parameters:
- description: API key configuration
in: body
name: key
required: true
schema:
$ref: '#/definitions/server.CreateKeyRequest'
produces:
- application/json
responses:
"201":
description: Created API key with plain-text key
schema:
$ref: '#/definitions/server.CreateKeyResponse'
"400":
description: Invalid request body or validation error
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
summary: Create a new API key
tags:
- Keys
/api/v1/auth/keys/{id}:
delete:
description: Deletes an API key by ID
parameters:
- description: Key ID
in: path
name: id
required: true
type: integer
responses:
"204":
description: API key deleted successfully
"400":
description: Invalid key ID
schema:
type: string
"404":
description: API key not found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: Delete an API key
tags:
- Keys
get:
description: Returns details for a specific API key by ID (excludes key hash
and plain-text key)
parameters:
- description: Key ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: API key details
schema:
$ref: '#/definitions/server.KeyResponse'
"400":
description: Invalid key ID
schema:
type: string
"404":
description: API key not found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: Get details of a specific API key
tags:
- Keys
/api/v1/auth/keys/{id}/permissions:
get:
description: Returns the instance-level permissions for a specific API key (includes
instance names)
parameters:
- description: Key ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: List of key permissions
schema:
items:
$ref: '#/definitions/server.KeyPermissionResponse'
type: array
"400":
description: Invalid key ID
schema:
type: string
"404":
description: API key not found
schema:
type: string
"500":
description: Internal Server Error
schema:
type: string
security:
- ApiKeyAuth: []
summary: Get API key permissions
tags:
- Keys
/api/v1/backends/llama-cpp/devices: /api/v1/backends/llama-cpp/devices:
get: get:
description: Returns a list of available devices for the llama server description: Returns a list of available devices for the llama server

View File

@@ -85,7 +85,7 @@ type DatabaseConfig struct {
// Connection settings // Connection settings
MaxOpenConnections int `yaml:"max_open_connections" json:"max_open_connections"` MaxOpenConnections int `yaml:"max_open_connections" json:"max_open_connections"`
MaxIdleConnections int `yaml:"max_idle_connections" json:"max_idle_connections"` MaxIdleConnections int `yaml:"max_idle_connections" json:"max_idle_connections"`
ConnMaxLifetime time.Duration `yaml:"connection_max_lifetime" json:"connection_max_lifetime"` ConnMaxLifetime time.Duration `yaml:"connection_max_lifetime" json:"connection_max_lifetime" swaggertype:"string" example:"1h"`
} }
// InstancesConfig contains instance management configuration // InstancesConfig contains instance management configuration

View File

@@ -11,12 +11,14 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
) )
// InstancePermission defines the permissions for an API key on a specific instance.
type InstancePermission struct { type InstancePermission struct {
InstanceID int `json:"instance_id"` InstanceID int `json:"instance_id"`
CanInfer bool `json:"can_infer"` CanInfer bool `json:"can_infer"`
CanViewLogs bool `json:"can_view_logs"` CanViewLogs bool `json:"can_view_logs"`
} }
// CreateKeyRequest represents the request body for creating a new API key.
type CreateKeyRequest struct { type CreateKeyRequest struct {
Name string Name string
PermissionMode auth.PermissionMode PermissionMode auth.PermissionMode
@@ -24,31 +26,34 @@ type CreateKeyRequest struct {
InstancePermissions []InstancePermission InstancePermissions []InstancePermission
} }
// CreateKeyResponse represents the response returned when creating a new API key.
type CreateKeyResponse struct { type CreateKeyResponse struct {
ID int `json:"id"` ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
UserID string `json:"user_id"` UserID string `json:"user_id"`
PermissionMode auth.PermissionMode `json:"permission_mode"` PermissionMode auth.PermissionMode `json:"permission_mode"`
ExpiresAt *int64 `json:"expires_at"` ExpiresAt *int64 `json:"expires_at"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
LastUsedAt *int64 `json:"last_used_at"` LastUsedAt *int64 `json:"last_used_at"`
Key string `json:"key"` Key string `json:"key"`
} }
// KeyResponse represents an API key in responses for list and get operations.
type KeyResponse struct { type KeyResponse struct {
ID int `json:"id"` ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
UserID string `json:"user_id"` UserID string `json:"user_id"`
PermissionMode auth.PermissionMode `json:"permission_mode"` PermissionMode auth.PermissionMode `json:"permission_mode"`
ExpiresAt *int64 `json:"expires_at"` ExpiresAt *int64 `json:"expires_at"`
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
CreatedAt int64 `json:"created_at"` CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` UpdatedAt int64 `json:"updated_at"`
LastUsedAt *int64 `json:"last_used_at"` LastUsedAt *int64 `json:"last_used_at"`
} }
// KeyPermissionResponse represents the permissions for an API key on a specific instance.
type KeyPermissionResponse struct { type KeyPermissionResponse struct {
InstanceID int `json:"instance_id"` InstanceID int `json:"instance_id"`
InstanceName string `json:"instance_name"` InstanceName string `json:"instance_name"`
@@ -56,8 +61,18 @@ type KeyPermissionResponse struct {
CanViewLogs bool `json:"can_view_logs"` CanViewLogs bool `json:"can_view_logs"`
} }
// CreateInferenceKey handles POST /api/v1/keys // CreateKey godoc
func (h *Handler) CreateInferenceKey() http.HandlerFunc { // @Summary Create a new API key
// @Description Creates a new API key with the specified permissions and returns the plain-text key (only shown once)
// @Tags Keys
// @Accept json
// @Produce json
// @Param key body CreateKeyRequest true "API key configuration"
// @Success 201 {object} CreateKeyResponse "Created API key with plain-text key"
// @Failure 400 {string} string "Invalid request body or validation error"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/auth/keys [post]
func (h *Handler) CreateKey() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var req CreateKeyRequest var req CreateKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
@@ -172,8 +187,16 @@ func (h *Handler) CreateInferenceKey() http.HandlerFunc {
} }
} }
// ListInferenceKeys handles GET /api/v1/keys // ListKeys godoc
func (h *Handler) ListInferenceKeys() http.HandlerFunc { // @Summary List all API keys
// @Description Returns a list of all API keys for the system user (excludes key hash and plain-text key)
// @Tags Keys
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} KeyResponse "List of API keys"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/auth/keys [get]
func (h *Handler) ListKeys() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
keys, err := h.authStore.GetUserKeys(r.Context(), "system") keys, err := h.authStore.GetUserKeys(r.Context(), "system")
if err != nil { if err != nil {
@@ -202,8 +225,19 @@ func (h *Handler) ListInferenceKeys() http.HandlerFunc {
} }
} }
// GetInferenceKey handles GET /api/v1/keys/{id} // GetKey godoc
func (h *Handler) GetInferenceKey() http.HandlerFunc { // @Summary Get details of a specific API key
// @Description Returns details for a specific API key by ID (excludes key hash and plain-text key)
// @Tags Keys
// @Security ApiKeyAuth
// @Produce json
// @Param id path int true "Key ID"
// @Success 200 {object} KeyResponse "API key details"
// @Failure 400 {string} string "Invalid key ID"
// @Failure 404 {string} string "API key not found"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/auth/keys/{id} [get]
func (h *Handler) GetKey() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
idStr := chi.URLParam(r, "id") idStr := chi.URLParam(r, "id")
id, err := strconv.Atoi(idStr) id, err := strconv.Atoi(idStr)
@@ -240,8 +274,18 @@ func (h *Handler) GetInferenceKey() http.HandlerFunc {
} }
} }
// DeleteInferenceKey handles DELETE /api/v1/keys/{id} // DeleteKey godoc
func (h *Handler) DeleteInferenceKey() http.HandlerFunc { // @Summary Delete an API key
// @Description Deletes an API key by ID
// @Tags Keys
// @Security ApiKeyAuth
// @Param id path int true "Key ID"
// @Success 204 "API key deleted successfully"
// @Failure 400 {string} string "Invalid key ID"
// @Failure 404 {string} string "API key not found"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/auth/keys/{id} [delete]
func (h *Handler) DeleteKey() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
idStr := chi.URLParam(r, "id") idStr := chi.URLParam(r, "id")
id, err := strconv.Atoi(idStr) id, err := strconv.Atoi(idStr)
@@ -264,8 +308,19 @@ func (h *Handler) DeleteInferenceKey() http.HandlerFunc {
} }
} }
// GetInferenceKeyPermissions handles GET /api/v1/keys/{id}/permissions // GetKeyPermissions godoc
func (h *Handler) GetInferenceKeyPermissions() http.HandlerFunc { // @Summary Get API key permissions
// @Description Returns the instance-level permissions for a specific API key (includes instance names)
// @Tags Keys
// @Security ApiKeyAuth
// @Produce json
// @Param id path int true "Key ID"
// @Success 200 {array} KeyPermissionResponse "List of key permissions"
// @Failure 400 {string} string "Invalid key ID"
// @Failure 404 {string} string "API key not found"
// @Failure 500 {string} string "Internal Server Error"
// @Router /api/v1/auth/keys/{id}/permissions [get]
func (h *Handler) GetKeyPermissions() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
idStr := chi.URLParam(r, "id") idStr := chi.URLParam(r, "id")
id, err := strconv.Atoi(idStr) id, err := strconv.Atoi(idStr)

View File

@@ -49,11 +49,11 @@ func SetupRouter(handler *Handler) *chi.Mux {
// API key management endpoints // API key management endpoints
r.Route("/auth", func(r chi.Router) { r.Route("/auth", func(r chi.Router) {
r.Route("/keys", func(r chi.Router) { r.Route("/keys", func(r chi.Router) {
r.Post("/", handler.CreateInferenceKey()) // Create API key r.Post("/", handler.CreateKey()) // Create API key
r.Get("/", handler.ListInferenceKeys()) // List API keys r.Get("/", handler.ListKeys()) // List API keys
r.Get("/{id}", handler.GetInferenceKey()) // Get API key details r.Get("/{id}", handler.GetKey()) // Get API key details
r.Delete("/{id}", handler.DeleteInferenceKey()) // Delete API key r.Delete("/{id}", handler.DeleteKey()) // Delete API key
r.Get("/{id}/permissions", handler.GetInferenceKeyPermissions()) // Get key permissions r.Get("/{id}/permissions", handler.GetKeyPermissions()) // Get key permissions
}) })
}) })