diff --git a/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml b/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml index 829889d9..7a75a495 100644 --- a/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml +++ b/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml @@ -1,3 +1,4 @@ +--- openapi: 3.0.3 info: title: Margo Workload Management API @@ -62,29 +63,20 @@ paths: type: object description: New client onboarded successfully. '400': + description: Bad Request content: - application/json: + application/problem+json: schema: - properties: - error: - example: Invalid certificate - type: string - type: object - description: Invalid certificate format or structure. + $ref: '#/components/schemas/ProblemDetail' '403': + description: Forbidden — Certificate not trusted or client rejected content: - application/json: + application/problem+json: schema: - properties: - error: - example: Client rejected - type: string - type: object - description: Client certificate not trusted or client rejected. + $ref: '#/components/schemas/ProblemDetail' security: - - PayloadSignature: [] + - PayloadSignature: [] summary: Complete onboarding with client certificate - /api/v1/clients/{clientId}/capabilities/{deviceId}: post: summary: Report device capabilities @@ -111,15 +103,35 @@ paths: '201': description: Capabilities reported successfully '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included. + description: Bad Request + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. + description: Unauthorized — Signature verification failed + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '403': - description: Client certificate is not trusted or has been revoked. + description: Forbidden — Certificate not trusted or client rejected + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '404': - description: No client with the given `clientID` was found. + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '422': - description: Request body includes a semantic error. + description: Unprocessable Entity — Semantic error in request body + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' put: summary: Update device capabilities (Update) security: @@ -145,15 +157,35 @@ paths: '201': description: Capabilities reported successfully '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included. + description: Bad Request + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. + description: Unauthorized — Signature verification failed + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '403': - description: Client certificate is not trusted or has been revoked. + description: Forbidden — Certificate not trusted or client rejected + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '404': - description: No client with the given `clientID` was found. + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '422': - description: Request body includes a semantic error. + description: Unprocessable Entity — Semantic error in request body + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' delete: summary: Remove device (Unregister) security: @@ -173,13 +205,29 @@ paths: '204': description: Device capabilities removed successfully '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included. + description: Bad Request + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. + description: Unauthorized — Signature verification failed + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '403': - description: Client certificate is not trusted or has been revoked. + description: Forbidden — Certificate not trusted or client rejected + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '404': - description: Client or device not found. + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' /api/v1/clients/{clientId}/bundles/{digest}: get: summary: Retrieve bundle information for a specific device and digest @@ -224,19 +272,29 @@ paths: description: Gzip-compressed tar containing one YAML file per deployment. '304': description: Representation not modified - '404': - description: Bundle not found for the given digest '400': - description: Invalid request. - # TBD - # '500': - # $ref: '#/components/responses/ErrorResponse' - + description: Bad Request + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' + '404': + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' + '500': + description: Internal Server Error + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' /api/v1/clients/{clientId}/deployments: get: summary: Retrieve the complete desired state for all workloads assigned to a device security: - - PayloadSignature: [] + - PayloadSignature: [] parameters: - name: clientId in: path @@ -250,15 +308,15 @@ paths: schema: type: string description: > - ETag value of the last successfully synced manifest. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest. + ETag value of the last successfully synced manifest. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest. - name: Accept in: header required: false schema: type: string description: > - Indicates which manifest formats the client supports. - Supported values: application/vnd.margo.manifest.v1+json. + Indicates which manifest formats the client supports. Supported + values: application/vnd.margo.manifest.v1+json. responses: '200': description: Manifest returned in the negotiated format @@ -279,13 +337,21 @@ paths: description: Not Modified - Manifest has not changed '406': description: Not Acceptable - Server cannot generate a response matching the Accept header - - + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' + '500': + description: Internal Server Error + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}: get: summary: Retrieve an individual ApplicationDeployment YAML file security: - - PayloadSignature: [] + - PayloadSignature: [] description: > This endpoint is used by the client to fetch the YAML for a single ApplicationDeployment after it has processed a new State Manifest and identified a small number of new or updated deployments. This allows for highly efficient, incremental updates without needing to download the full bundle. To make individual workload retrievals race-free and cache-friendly, this endpoint is content-addressable: the digest of the expected YAML is part of the URL. This guarantees immutability of the fetched resource and prevents a time-of-check / time-of-use race where a deployment changes between manifest retrieval and content fetch. @@ -334,7 +400,7 @@ paths: ETag: schema: type: string - description: > + description: > The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest. Cache-Control: schema: @@ -349,9 +415,20 @@ paths: schema: type: string description: Raw YAML content of the ApplicationDeployment + '304': + description: Not Modified '404': - description: Deployment not found for the given digest - + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' + '500': + description: Internal Server Error + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' /api/v1/clients/{clientId}/deployments/{deploymentId}/status: post: summary: Report deployment status @@ -378,14 +455,35 @@ paths: '200': description: The deployment status was added, or updated, successfully. '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included. + description: Bad Request + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. + description: Unauthorized — Signature verification failed + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '403': - description: Client certificate is not trusted or has been revoked. + description: Forbidden — Certificate not trusted or client rejected + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' '422': - description: Request body includes a semantic error. - + description: Unprocessable Entity — Semantic error in request body + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetail' + '500': + description: Internal Server Error + content: + application/problem+json: + schema: + $ref: "#/components/schemas/ProblemDetail" components: securitySchemes: # TODO: fix this as we are following RFC 9421, instead of a custom signature header field @@ -397,6 +495,44 @@ components: Base64-encoded payload signature using SHA-256 and device certificate. Format: public_key;digital_signature schemas: + ProblemDetail: + type: object + description: > + RFC 9457 Problem Details for HTTP APIs. Returned with Content-Type: + application/problem+json. See `https://www.rfc-editor.org/rfc/rfc9457` + required: + - type + - title + - status + properties: + type: + type: string + format: uri + description: > + URI reference that identifies the problem type. Consumers can + dereference this URI for human-readable documentation. + example: "`https://margo.org/problems/invalid-certificate`" + title: + type: string + description: Short human-readable summary of the problem type. + example: Invalid Certificate + status: + type: integer + description: HTTP status code. + example: 400 + detail: + type: string + description: > + Human-readable explanation specific to this occurrence of the + problem. + example: Certificate signature verification failed + instance: + type: string + format: uri + description: | + URI reference identifying the specific occurrence of the problem. + example: /api/v1/onboarding + additionalProperties: true ManifestVersion: type: number description: > @@ -460,7 +596,7 @@ components: - deployments properties: manifestVersion: - $ref: '#/components/schemas/ManifestVersion' + $ref: '#/components/schemas/ManifestVersion' bundle: $ref: '#/components/schemas/DeploymentBundleRef' deployments: @@ -604,7 +740,6 @@ components: type: type: string enum: [ethernet, wifi, cellular, bluetooth, usb, canbus, rs232] - # app deployment struct added here for ease of programming, the code generators will generate the structs # for the actual app deployment yaml and parsing would be easy to do appDeploymentManifest: @@ -672,6 +807,7 @@ components: type: object description: Compose Application Deployment Profile Component required: [name, properties] + properties: name: type: string @@ -727,7 +863,6 @@ components: required: [value, targets] properties: value: - # type: object description: Value of the parameter additionalProperties: true x-go-type: interface{} @@ -761,4 +896,4 @@ components: description: Deployment profile parameters: $ref: '#/components/schemas/appDeploymentParams' - description: Parameters for the deployment \ No newline at end of file + description: Parameters for the deployment