Merge the wilm endpoint-monitor and channel-distribution work into main
Six commits from wilm-import: the squashed import, route documentation, the channel remap onto our tag-and-trunk model, the project map, parallel test support, and the four smaller review findings. Merged rather than cherry-picked: the published mirror rewrites hashes, so the commits do not apply one at a time against our history even though the squashed diff applies clean. Scope: product # Conflicts: # docs/PROJECT-MAP.md
This commit is contained in:
45
docs/DEV-BUILD-TEST.md
Normal file
45
docs/DEV-BUILD-TEST.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# ShopDB dev build - quick test
|
||||
|
||||
Two dev builds you can stand up on a Windows box with Docker Desktop. You run
|
||||
one PowerShell script: it checks your dependencies (offers to winget-install
|
||||
anything missing), then PULLS a prebuilt image from GHCR and starts the stack in
|
||||
Docker. Nothing is compiled on your machine - no Node, no npm, no source build -
|
||||
so it works on a box that has only Docker installed.
|
||||
|
||||
## What you need
|
||||
|
||||
- Windows with Docker Desktop running.
|
||||
- Git for Windows (`winget install Git.Git`).
|
||||
- A GitHub login for this private repo/registry already stored on the box. If
|
||||
you have cloned this repo before, or signed in to GitHub in Visual Studio or
|
||||
VS Code, you already have it - the script uses that stored credential
|
||||
automatically. If Docker cannot pull the image, sign in once with
|
||||
`docker login ghcr.io` (use a GitHub username and a personal access token that
|
||||
has `read:packages`), then re-run the launcher.
|
||||
|
||||
## Get the launcher
|
||||
|
||||
You will be sent `Start-ShopDBDev.ps1` directly. Save it anywhere (for example
|
||||
your Downloads folder) and open PowerShell in that folder.
|
||||
|
||||
## Bleeding edge (main, the trunk)
|
||||
|
||||
powershell -ExecutionPolicy Bypass -File .\Start-ShopDBDev.ps1 -Channel edge
|
||||
|
||||
Comes up at https://localhost:5011. Red DEV badge in the sidebar. Pulls the
|
||||
`edge` image.
|
||||
|
||||
## Stable (newest release tag)
|
||||
|
||||
powershell -ExecutionPolicy Bypass -File .\Start-ShopDBDev.ps1 -Channel stable
|
||||
|
||||
Comes up at https://localhost:5001. No DEV badge. Pulls the `stable` image.
|
||||
|
||||
## Notes
|
||||
|
||||
- Both stacks can run at the same time - they use different ports and separate
|
||||
Docker volumes, so they do not collide and each keeps its own database.
|
||||
- Each launch pulls the latest image for the channel, so re-running the launcher
|
||||
is how you pick up a new build. No local rebuild step.
|
||||
- First page load shows a self-signed cert warning (expected for a dev box).
|
||||
- Stop a stack: `docker compose -p shopdb-stable down` (or `shopdb-edge`).
|
||||
@@ -27,7 +27,7 @@ with `flask plugin upgrade-all`. Both are needed on a deploy.
|
||||
| backups | `backups0003clearlastseen` |
|
||||
| computers | `computers0004policies` |
|
||||
| employees | `employees0002photo` |
|
||||
| endpoints | `endpoints0005cmdpin` |
|
||||
| endpoints | `endpoints0009opreports` |
|
||||
| geenforce | `geenforce0004minlib` |
|
||||
| guides | `guides0001baseline` |
|
||||
| knowledgebase | `knowledgebase0001anchor` |
|
||||
@@ -90,6 +90,6 @@ Manifest-less directories under `plugins/` are core frontend surface and always
|
||||
|
||||
## Size
|
||||
|
||||
- test functions defined: **1587** (parametrised cases collect higher)
|
||||
- documented API paths: **346** (`docs/openapi.json`, regenerate with `scripts/gen_openapi.py`)
|
||||
- test functions defined: **1619** (parametrised cases collect higher)
|
||||
- documented API paths: **353** (`docs/openapi.json`, regenerate with `scripts/gen_openapi.py`)
|
||||
|
||||
|
||||
0
docs/ShopDB-Planner-Tasks-v2.csv
Normal file
0
docs/ShopDB-Planner-Tasks-v2.csv
Normal file
|
|
@@ -3773,10 +3773,10 @@
|
||||
"endpoints": [
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/endpoints",
|
||||
"path": "/api/endpoints/",
|
||||
"auth": "endpoints.view",
|
||||
"params": "query: search (hostname substring)",
|
||||
"purpose": "List endpoints reporting through the ShopDB agent, with last-seen and online state",
|
||||
"purpose": "List endpoint states. Registered both with and without the trailing slash, so both forms are described here",
|
||||
"example": "curl -H \"Authorization: Bearer $TOKEN\" http://localhost:5001/api/endpoints"
|
||||
},
|
||||
{
|
||||
@@ -3922,6 +3922,86 @@
|
||||
"params": "path: command_id; body: the command outcome (status, output)",
|
||||
"purpose": "Agent reports a claimed command result. Finalizes the command row and, for MTConnect actions that observed run state, caches that on the EndpointState so the UI toggle reflects reality between polls - both in one commit. Collector-token auth, not JWT",
|
||||
"example": "curl -X POST -H \"X-Collector-Key: $KEY\" -H 'Content-Type: application/json' -d '{\"status\":\"succeeded\",\"output\":\"ok\"}' http://localhost:5001/api/endpoints/commands/1/result"
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors",
|
||||
"method": "GET",
|
||||
"auth": "jwt + require_permission endpoints.view",
|
||||
"params": "none",
|
||||
"purpose": "List every monitor definition, shipped and local, ordered shipped-first then by display name",
|
||||
"example": "curl http://localhost:5001/api/endpoints/monitors -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors",
|
||||
"method": "POST",
|
||||
"auth": "jwt + require_role admin",
|
||||
"params": "body: kind (process|service, required), displayname (required), processname (required for process), servicename (required for service), launchpath, datacollectorpath, logcollectorpath, isactive (default true)",
|
||||
"purpose": "Create a local monitor definition; source is forced to 'local' so a caller cannot mint a shipped row",
|
||||
"example": "curl -X POST http://localhost:5001/api/endpoints/monitors -H \"Authorization: Bearer $TOK\" -H 'Content-Type: application/json' -d '{\"kind\":\"service\",\"displayname\":\"Spooler\",\"servicename\":\"Spooler\"}'"
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors/<monitor_id>",
|
||||
"method": "PUT",
|
||||
"auth": "jwt + require_role admin",
|
||||
"params": "path: monitor_id; body: same fields as create, all optional",
|
||||
"purpose": "Update a local monitor definition; 403 on a shipped row, which is product-owned and read-only",
|
||||
"example": "curl -X PUT http://localhost:5001/api/endpoints/monitors/4 -H \"Authorization: Bearer $TOK\" -H 'Content-Type: application/json' -d '{\"isactive\":false}'"
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors/<monitor_id>",
|
||||
"method": "DELETE",
|
||||
"auth": "jwt + require_role admin",
|
||||
"params": "path: monitor_id",
|
||||
"purpose": "Delete a local monitor definition; 403 on a shipped row",
|
||||
"example": "curl -X DELETE http://localhost:5001/api/endpoints/monitors/4 -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors/resolve",
|
||||
"method": "GET",
|
||||
"auth": "jwt + require_permission endpoints.view",
|
||||
"params": "query: pctype (required)",
|
||||
"purpose": "Resolve the monitor set a PC type should watch: shipped defaults for 'Shopfloor PC' plus whatever active site policy attaches to that type. The human-facing view of what the agent will be told",
|
||||
"example": "curl 'http://localhost:5001/api/endpoints/monitors/resolve?pctype=Shopfloor+PC' -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/monitors/resolved",
|
||||
"method": "GET",
|
||||
"auth": "endpoints collector API key (X-API-Key/Bearer), not JWT",
|
||||
"params": "query: hostname (required)",
|
||||
"purpose": "Agent runtime watch-list. The agent calls this each telemetry cycle and receives {processes[], services[]} shaped like its own MonitorConfig, so a policy-attached monitor is watched without editing appsettings.json on the bay. Unknown hostname is a 404; a PC type with no monitors returns empty lists",
|
||||
"example": "curl 'http://localhost:5001/api/endpoints/monitors/resolved?hostname=F7MHPF24' -H \"X-API-Key: $ENDPOINTS_KEY\""
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/operatorreports",
|
||||
"method": "POST",
|
||||
"auth": "endpoints collector API key (X-API-Key/Bearer), not JWT",
|
||||
"params": "multipart/form-data: hostname (required), reason (default 'Other (free text)', truncated to 128), details, screenshot (png, 10 MB cap)",
|
||||
"purpose": "Agent uploads one operator issue report captured from the tray. The hostname must resolve to a computer asset. The screenshot is stored under a server-generated uuid filename; a retention sweep runs opportunistically so the feed stays bounded without a scheduler",
|
||||
"example": "curl -X POST http://localhost:5001/api/endpoints/operatorreports -H \"X-API-Key: $ENDPOINTS_KEY\" -F hostname=F7MHPF24 -F 'details=Machine will not home' -F screenshot=@shot.png"
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/panel/<asset_id>/operatorreports",
|
||||
"method": "GET",
|
||||
"auth": "jwt + require_permission endpoints.view",
|
||||
"params": "path: asset_id",
|
||||
"purpose": "Operator Reports asset panel: this endpoint's reports newest first, each carrying a hasimage flag so the viewer knows whether to request the screenshot",
|
||||
"example": "curl http://localhost:5001/api/endpoints/panel/46/operatorreports -H \"Authorization: Bearer $TOK\""
|
||||
},
|
||||
{
|
||||
"path": "/api/endpoints/operatorreports/<operatorreportid>/image",
|
||||
"method": "GET",
|
||||
"auth": "jwt + require_permission endpoints.view",
|
||||
"params": "path: operatorreportid",
|
||||
"purpose": "Serve one operator report's screenshot, hardened with the shared upload headers (CSP sandbox + nosniff); 404 when the report carries no image",
|
||||
"example": "curl http://localhost:5001/api/endpoints/operatorreports/12/image -H \"Authorization: Bearer $TOK\" -o shot.png"
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/api/endpoints",
|
||||
"auth": "endpoints.view",
|
||||
"params": "query: search (hostname substring)",
|
||||
"purpose": "List endpoint states. Registered both with and without the trailing slash, so both forms are described here",
|
||||
"example": "curl -H \"Authorization: Bearer $TOKEN\" http://localhost:5001/api/endpoints"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -21826,8 +21826,8 @@
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "List endpoints reporting through the ShopDB agent, with last-seen and online state",
|
||||
"description": "List endpoints reporting through the ShopDB agent, with last-seen and online state\n\n**Auth:** endpoints.view\n\n**Params:** query: search (hostname substring)\n\n**Example:**\n```\ncurl -H \"Authorization: Bearer $TOKEN\" http://localhost:5001/api/endpoints\n```",
|
||||
"summary": "List endpoint states. Registered both with and without the trailing slash, so both forms are described here",
|
||||
"description": "List endpoint states. Registered both with and without the trailing slash, so both forms are described here\n\n**Auth:** endpoints.view\n\n**Params:** query: search (hostname substring)\n\n**Example:**\n```\ncurl -H \"Authorization: Bearer $TOKEN\" http://localhost:5001/api/endpoints\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
@@ -22718,6 +22718,432 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/endpoints/monitors": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "List every monitor definition, shipped and local, ordered shipped-first then by display name",
|
||||
"description": "List every monitor definition, shipped and local, ordered shipped-first then by display name\n\n**Auth:** jwt + require_permission endpoints.view\n\n**Params:** none\n\n**Example:**\n```\ncurl http://localhost:5001/api/endpoints/monitors -H \"Authorization: Bearer $TOK\"\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Create a local monitor definition; source is forced to 'local' so a caller cannot mint a shipped row",
|
||||
"description": "Create a local monitor definition; source is forced to 'local' so a caller cannot mint a shipped row\n\n**Auth:** jwt + require_role admin\n\n**Params:** body: kind (process|service, required), displayname (required), processname (required for process), servicename (required for service), launchpath, datacollectorpath, logcollectorpath, isactive (default true)\n\n**Example:**\n```\ncurl -X POST http://localhost:5001/api/endpoints/monitors -H \"Authorization: Bearer $TOK\" -H 'Content-Type: application/json' -d '{\"kind\":\"service\",\"displayname\":\"Spooler\",\"servicename\":\"Spooler\"}'\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "body: kind (process|service, required), displayname (required), processname (required for process), servicename (required for service), launchpath, datacollectorpath, logcollectorpath, isactive (default true)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/endpoints/monitors/{monitor_id}": {
|
||||
"put": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Update a local monitor definition; 403 on a shipped row, which is product-owned and read-only",
|
||||
"description": "Update a local monitor definition; 403 on a shipped row, which is product-owned and read-only\n\n**Auth:** jwt + require_role admin\n\n**Params:** path: monitor_id; body: same fields as create, all optional\n\n**Example:**\n```\ncurl -X PUT http://localhost:5001/api/endpoints/monitors/4 -H \"Authorization: Bearer $TOK\" -H 'Content-Type: application/json' -d '{\"isactive\":false}'\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
},
|
||||
"404": {
|
||||
"description": "No such record."
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "monitor_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "path: monitor_id; body: same fields as create, all optional"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Delete a local monitor definition; 403 on a shipped row",
|
||||
"description": "Delete a local monitor definition; 403 on a shipped row\n\n**Auth:** jwt + require_role admin\n\n**Params:** path: monitor_id\n\n**Example:**\n```\ncurl -X DELETE http://localhost:5001/api/endpoints/monitors/4 -H \"Authorization: Bearer $TOK\"\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
},
|
||||
"404": {
|
||||
"description": "No such record."
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "monitor_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/endpoints/monitors/resolve": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Resolve the monitor set a PC type should watch: shipped defaults for 'Shopfloor PC' plus whatever active site policy...",
|
||||
"description": "Resolve the monitor set a PC type should watch: shipped defaults for 'Shopfloor PC' plus whatever active site policy attaches to that type. The human-facing view of what the agent will be told\n\n**Auth:** jwt + require_permission endpoints.view\n\n**Params:** query: pctype (required)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/endpoints/monitors/resolve?pctype=Shopfloor+PC' -H \"Authorization: Bearer $TOK\"\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/endpoints/monitors/resolved": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Agent runtime watch-list. The agent calls this each telemetry cycle and receives {processes[], services[]} shaped like...",
|
||||
"description": "Agent runtime watch-list. The agent calls this each telemetry cycle and receives {processes[], services[]} shaped like its own MonitorConfig, so a policy-attached monitor is watched without editing appsettings.json on the bay. Unknown hostname is a 404; a PC type with no monitors returns empty lists\n\n**Auth:** endpoints collector API key (X-API-Key/Bearer), not JWT\n\n**Params:** query: hostname (required)\n\n**Example:**\n```\ncurl 'http://localhost:5001/api/endpoints/monitors/resolved?hostname=F7MHPF24' -H \"X-API-Key: $ENDPOINTS_KEY\"\n```",
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/endpoints/operatorreports": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Agent uploads one operator issue report captured from the tray. The hostname must resolve to a computer asset. The...",
|
||||
"description": "Agent uploads one operator issue report captured from the tray. The hostname must resolve to a computer asset. The screenshot is stored under a server-generated uuid filename; a retention sweep runs opportunistically so the feed stays bounded without a scheduler\n\n**Auth:** endpoints collector API key (X-API-Key/Bearer), not JWT\n\n**Params:** multipart/form-data: hostname (required), reason (default 'Other (free text)', truncated to 128), details, screenshot (png, 10 MB cap)\n\n**Example:**\n```\ncurl -X POST http://localhost:5001/api/endpoints/operatorreports -H \"X-API-Key: $ENDPOINTS_KEY\" -F hostname=F7MHPF24 -F 'details=Machine will not home' -F screenshot=@shot.png\n```",
|
||||
"security": [
|
||||
{
|
||||
"apiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
}
|
||||
},
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "multipart/form-data: hostname (required), reason (default 'Other (free text)', truncated to 128), details, screenshot (png, 10 MB cap)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/endpoints/panel/{asset_id}/operatorreports": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Operator Reports asset panel: this endpoint's reports newest first, each carrying a hasimage flag so the viewer knows...",
|
||||
"description": "Operator Reports asset panel: this endpoint's reports newest first, each carrying a hasimage flag so the viewer knows whether to request the screenshot\n\n**Auth:** jwt + require_permission endpoints.view\n\n**Params:** path: asset_id\n\n**Example:**\n```\ncurl http://localhost:5001/api/endpoints/panel/46/operatorreports -H \"Authorization: Bearer $TOK\"\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
},
|
||||
"404": {
|
||||
"description": "No such record."
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "asset_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/endpoints/operatorreports/{operatorreportid}/image": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"plugin-endpoints"
|
||||
],
|
||||
"summary": "Serve one operator report's screenshot, hardened with the shared upload headers (CSP sandbox + nosniff); 404 when the...",
|
||||
"description": "Serve one operator report's screenshot, hardened with the shared upload headers (CSP sandbox + nosniff); 404 when the report carries no image\n\n**Auth:** jwt + require_permission endpoints.view\n\n**Params:** path: operatorreportid\n\n**Example:**\n```\ncurl http://localhost:5001/api/endpoints/operatorreports/12/image -H \"Authorization: Bearer $TOK\" -o shot.png\n```",
|
||||
"security": [
|
||||
{
|
||||
"bearerAuth": []
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success. Body is the success_response envelope: {status, data, meta}.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/SuccessEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Error. Body is the error envelope; the code and message are nested under data.error.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"$ref": "#/components/schemas/ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Missing or invalid credentials."
|
||||
},
|
||||
"403": {
|
||||
"description": "Authenticated, but not permitted."
|
||||
},
|
||||
"404": {
|
||||
"description": "No such record."
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "operatorreportid",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/scripts": {
|
||||
"get": {
|
||||
"tags": [
|
||||
|
||||
Reference in New Issue
Block a user