-
Notifications
You must be signed in to change notification settings - Fork 20
Description
Summary
Scripts are diagnostic programs that can be uploaded to the server and later executed on entities. This issue covers the script management endpoints (upload, list, read metadata, delete). Script execution is covered in a separate issue.
Proposed solution
1. POST /api/v1/{entity-path}/scripts
Upload a new diagnostic script to an entity.
Applies to entity types: Components, Apps
Path parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
{entity-path} |
URL segment | Yes | e.g., components/engine_ecu or apps/temp_sensor |
Request: Content-Type: multipart/form-data
The multipart body should contain:
file- the script binary/text contentmetadata(optional) - JSON with script metadata:
{
"name": "Sensor Calibration Check",
"description": "Validates sensor calibration values against known thresholds",
"parameters_schema": {
"type": "object",
"properties": {
"threshold": { "type": "number", "default": 0.1 }
}
}
}Response 201 Created:
{
"id": "script_001",
"name": "Sensor Calibration Check",
"href": "/api/v1/apps/temp_sensor/scripts/script_001"
}Error responses:
| Status | Error Code | When |
|---|---|---|
400 |
invalid-request |
Missing file part, invalid metadata |
404 |
entity-not-found |
Entity doesn't exist |
415 |
invalid-request |
Unsupported content type (not multipart/form-data) |
2. GET /api/v1/{entity-path}/scripts
List all uploaded scripts for an entity.
Response 200 OK:
{
"items": [
{
"id": "script_001",
"name": "Sensor Calibration Check",
"description": "Validates sensor calibration values",
"href": "/api/v1/apps/temp_sensor/scripts/script_001"
},
{
"id": "script_002",
"name": "Network Diagnostics",
"description": "Tests DDS communication paths",
"href": "/api/v1/apps/temp_sensor/scripts/script_002"
}
]
}Each item is a ScriptDescription:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string |
Yes | Script identifier |
name |
string |
Yes | Human-readable name |
description |
string |
No | Script description |
href |
string |
Yes | URI to this script resource |
proximity_proof_required |
boolean |
No | Whether execution requires proof of co-location |
parameters_schema |
object |
No | JSON Schema for script input parameters |
3. GET /api/v1/{entity-path}/scripts/{script-id}
Read metadata for a specific script.
Path parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
{script-id} |
string |
Yes | Script identifier |
Response 200 OK: Returns a single ScriptDescription (same fields as list items, potentially with more detail).
Error responses:
| Status | Error Code | When |
|---|---|---|
404 |
resource-not-found |
Script doesn't exist on this entity |
4. DELETE /api/v1/{entity-path}/scripts/{script-id}
Delete an uploaded script. Cannot delete a script that is currently being executed.
Path parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
{script-id} |
string |
Yes | Script identifier |
Response 204 No Content - script deleted.
Error responses:
| Status | Error Code | When |
|---|---|---|
404 |
resource-not-found |
Script doesn't exist |
409 |
invalid-request |
Script is currently executing (has a running execution) |
Additional context
Architecture
- Create a
ScriptManagerclass that stores uploaded scripts - Storage: temporary directory on the filesystem with metadata JSON sidecar files
- Scripts do not survive server restart (unless using persistent storage)
- The manager needs thread-safe access to the script registry
Security considerations
- Script upload should require
adminoroperatorrole (integrate with auth middleware) - Store scripts in a controlled directory, not user-specified paths
- Consider file size limits (configurable, e.g., 10MB max)
cpp-httplib multipart handling
The library has built-in multipart/form-data parsing - access files via req.files:
auto file_it = req.files.find("file");
if (file_it != req.files.end()) {
const auto& file = file_it->second;
// file.content, file.filename, file.content_type
}Route registration
srv->Post((api_path("/components") + R"(/([^/]+)/scripts$)"), handler);
srv->Get((api_path("/components") + R"(/([^/]+)/scripts$)"), handler);
srv->Get((api_path("/components") + R"(/([^/]+)/scripts/([^/]+)$)"), handler);
srv->Delete((api_path("/components") + R"(/([^/]+)/scripts/([^/]+)$)"), handler);
// Same for /apps/Tests
- Unit test: upload script → 201
- Unit test: list scripts → returns uploaded scripts
- Unit test: get script metadata → correct data
- Unit test: delete script → 204
- Unit test: delete running script → 409
- Unit test: get nonexistent script → 404