diff --git a/public/specification/margo-management-interface/workload-management-api-1.0.0.yaml b/public/specification/margo-management-interface/workload-management-api-1.0.0.yaml deleted file mode 100644 index e2ab11f..0000000 --- a/public/specification/margo-management-interface/workload-management-api-1.0.0.yaml +++ /dev/null @@ -1,657 +0,0 @@ -openapi: 3.0.3 -info: - title: Margo Workload Management API - version: 1.0.0 - description: - API for managing workloads on Margo-compliant edge devices. - Includes the APIs for exchanging desired state and current state. - Communication is secured using server-side TLS (TLS 1.3 preferred), - and payloads are signed using X.509 certificates. - -servers: - - url: https://wfm.margo.org/ - description: Workload Fleet Manager API - -security: - - PayloadSignature: [] - -paths: - /api/v1/onboarding/certificate: - get: - summary: Download Root CA certificate - responses: - '200': - description: Root CA certificate - content: - application/json: - schema: - type: object - properties: - certificate: - type: string - description: Base64-encoded certificate text - /api/v1/onboarding: - post: - requestBody: - content: - application/json: - schema: - properties: - public_certificate: - description: Base64-encoded client certificate - type: string - type: object - required: true - responses: - '201': - content: - application/json: - schema: - properties: - client_id: - type: string - type: object - description: New client onboarded successfully. - '400': - content: - application/json: - schema: - properties: - error: - example: Invalid certificate - type: string - type: object - description: Invalid certificate format or structure. - '403': - content: - application/json: - schema: - properties: - error: - example: Client rejected - type: string - type: object - description: Client certificate not trusted or client rejected. - security: - - PayloadSignature: [] - summary: Complete onboarding with client certificate - - /api/v1/clients/{clientId}/capabilities: - post: - summary: Report device capabilities - security: - - PayloadSignature: [] - parameters: - - name: clientId - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DeviceCapabilitiesManifest' - responses: - '201': - description: Capabilities reported successfully - '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included. - '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. - '403': - description: Client certificate is not trusted or has been revoked. - '422': - description: Request body includes a semantic error. - put: - summary: Update device capabilities (Update) - security: - - PayloadSignature: [] - parameters: - - name: clientId - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DeviceCapabilitiesManifest' - responses: - '201': - description: Capabilities reported successfully - '400': - description: Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included. - '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. - '403': - description: Client certificate is not trusted or has been revoked. - '422': - description: Request body includes a semantic error. - - /api/v1/clients/{clientId}/bundles/{digest}: - get: - summary: Retrieve bundle information for a specific device and digest - security: - - PayloadSignature: [] - parameters: - - name: clientId - in: path - required: true - schema: - type: string - description: Unique identifier of the device-client - - name: digest - in: path - required: true - schema: - type: string - description: Content-addressable digest of the bundle archive. MUST conform to the 'digest' attribute in the Digest Specification and MUST equal the digest computed over the exact sequence of bytes (per Exact Bytes Rule) in the HTTP 200 OK response body. If the server cannot produce content whose digest matches this value it MUST return 404 Not Found. - - in: header - name: If-None-Match - required: false - schema: - type: string - description: Quoted ETag (same as digest) previously returned for this bundle. - responses: - '200': - description: Bundle archive (immutable) - headers: - ETag: - schema: - type: string - description: New ETag for the returned manifest - Cache-Control: - schema: - type: string - description: public, max-age=31536000, immutable - content: - application/vnd.margo.bundle.v1+tar+gzip: - schema: - type: string - format: binary - 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' - - /api/v1/clients/{clientId}/deployments: - get: - summary: Retrieve the complete desired state for all workloads assigned to a device - security: - - PayloadSignature: [] - parameters: - - name: clientId - in: path - required: true - schema: - type: string - description: The unique identifier of the Edge Compute Device making the request - - name: If-None-Match - in: header - required: false - 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. - - 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. - responses: - '200': - description: Manifest returned in the negotiated format - headers: - Content-Type: - schema: - type: string - description: Format of the returned manifest - ETag: - schema: - type: string - description: New ETag for the returned manifest - content: - application/vnd.margo.manifest.v1+json: - schema: - $ref: '#/components/schemas/UnsignedAppStateManifest' - '304': - description: Not Modified - Manifest has not changed - '406': - description: Not Acceptable - Server cannot generate a response matching the Accept header - - - /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}: - get: - summary: Retrieve an individual ApplicationDeployment YAML file - security: - - 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. - parameters: - - name: clientId - in: path - required: true - schema: - type: string - description: Unique identifier of the Edge Compute Device - - name: deploymentId - in: path - required: true - schema: - type: string - description: UUID of the ApplicationDeployment (metadata.annotations.id) - - name: digest - in: path - required: true - schema: - type: string - description: > - Content-addressable digest of the ApplicationDeployment YAML file. MUST conform to the Digest Specification and MUST equal the digest computed over the exact sequence of bytes (per Exact Bytes Rule) in the HTTP 200 OK response body. If the server cannot produce content whose digest matches this value it MUST return 404 Not Found. - - name: If-None-Match - in: header - required: false - schema: - type: string - description: > - Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest. - - name: Accept-Encoding - in: header - required: false - schema: - type: string - description: Indicates supported compression formats (e.g., gzip, br) - responses: - '200': - description: > - The response body is the raw ApplicationDeployment YAML file (Content-Type: application/yaml). The content MUST match the {digest} path segment; the server MUST return 404 if it does not have the exact digest referenced. - headers: - Content-Type: - schema: - type: string - description: application/yaml - ETag: - schema: - type: string - description: > - The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest. - Cache-Control: - schema: - type: string - description: public, max-age=31536000, immutable - Vary: - schema: - type: string - description: Accept-Encoding - content: - application/yaml: - schema: - type: string - description: Raw YAML content of the ApplicationDeployment - '404': - description: Deployment not found for the given digest - - /api/v1/clients/{clientId}/deployment/{deploymentId}/status: - post: - summary: Report deployment status - security: - - PayloadSignature: [] - parameters: - - name: clientId - in: path - required: true - schema: - type: string - - name: deploymentId - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DeploymentStatusManifest' - responses: - '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. - '401': - description: Signature verification failed. Ensure you are signing with the correct X.509 private key. - '403': - description: Client certificate is not trusted or has been revoked. - '422': - description: Request body includes a semantic error. - -components: - securitySchemes: - # TODO: fix this as we are following RFC 9421, instead of a custom signature header field - PayloadSignature: - type: apiKey - in: header - name: X-Payload-Signature - description: > - Base64-encoded payload signature using SHA-256 and device certificate. - Format: public_key;digital_signature - schemas: - ManifestVersion: - type: number - description: > - Monotonically increasing unsigned 64-bit integer in the inclusive range [1, 2^64-1]. - Prevents rollback attacks. The first manifest MUST use 1. - DeploymentBundleRef: - type: object - nullable: true - description: > - Describes a single archive containing all ApplicationDeployment documents. If there are zero deployments (deployments array is empty) the property MUST be present with the value null (it MUST NOT be omitted). - properties: - mediaType: - type: string - description: > - MUST be application/vnd.margo.bundle.v1+tar+gzip; a gzip-compressed tar whose root contains one or more ApplicationDeployment YAML files. If there are zero deployments then bundle MUST be null (an empty archive MUST NOT be served). The archive MUST contain exactly the set of YAML files referenced by deployments. - digest: - type: string - description: > - The digest of the bundle archive. MUST equal the digest computed over the exact sequence of bytes (per Exact Bytes Rule) in the bundle endpoint's HTTP 200 OK response body. - sizeBytes: - type: number - description: > - Unsigned 64-bit advisory estimate of the decoded payload length in bytes for the bundle archive. Provided for bandwidth estimation and update planning. MUST NOT be used for integrity; digest verification remains mandatory. - url: - type: string - description: > - Content-addressable retrieval endpoint of the form /api/v1/devices/{deviceId}/bundles/{digest} where {digest} equals bundle.digest. - DeploymentManifestRef: - type: object - description: > - Reference to a deployment manifest with content addressing and integrity verification. - required: - - deploymentId - - digest - - url - properties: - deploymentId: - type: string - description: > - The unique UUID from the ApplicationDeployment's metadata.annotations.id. - digest: - type: string - description: > - The digest of the individual ApplicationDeployment YAML file. MUST equal the digest computed over the exact sequence of bytes (per Exact Bytes Rule) in that deployment endpoint's HTTP 200 OK response body. - sizeBytes: - type: number - description: > - Unsigned 64-bit advisory estimate of the decoded payload length in bytes for the deployment YAML. Provided for planning or progress display. MUST NOT be used for integrity; digest verification remains mandatory. - url: - type: string - description: > - Content-addressable endpoint of the form /api/v1/devices/{deviceId}/deployments/{deploymentId}/{digest}. The {digest} MUST equal deployments[].digest; the referenced resource is immutable - UnsignedAppStateManifest: - type: object - required: - - manifestVersion - - bundle - - bundle.mediaType - - bundle.digest - - bundle.url - - deployments - properties: - manifestVersion: - $ref: '#/components/schemas/ManifestVersion' - bundle: - $ref: '#/components/schemas/DeploymentBundleRef' - deployments: - type: array - description: A list of deployment object references for the device. The reference contains some meta info and reference to the url where the deployment is available. - items: - $ref: '#/components/schemas/DeploymentManifestRef' - DeviceCapabilitiesManifest: - type: object - required: [apiVersion, kind, properties] - properties: - apiVersion: - type: string - kind: - type: string - enum: [DeviceCapabilities] - properties: - type: object - required: [id, vendor, modelNumber, serialNumber, roles, resources] - properties: - id: - type: string - vendor: - type: string - modelNumber: - type: string - serialNumber: - type: string - roles: - type: array - items: - type: string - enum: [Standalone Cluster, Cluster Leader, Standalone Device] - resources: - type: object - required: [cpu, memory, storage] - properties: - cpu: - type: object - properties: - cores: - type: number - memory: - type: string - storage: - type: string - - ComponentStatus: - type: object - required: [name, state] - properties: - name: - type: string - state: - type: string - enum: [Pending, Installing, Installed, Failed, Removing, Removed, Updating, Updated] - error: - type: object - properties: - code: - type: string - message: - type: string - - DeploymentStatusManifest: - type: object - required: [apiVersion, kind, deploymentId, status, components] - properties: - apiVersion: - type: string - kind: - type: string - enum: [DeploymentStatus] - deploymentId: - type: string - status: - type: object - required: [state] - properties: - state: - type: string - enum: [Pending, Installing, Installed, Failed, Removing, Removed, Updating, Updated] - error: - type: object - properties: - code: - type: string - message: - type: string - components: - type: array - items: - $ref: '#/components/schemas/ComponentStatus' - - # 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: - type: object - description: Application Deployment manifest - required: [apiVersion, kind, metadata, spec] - properties: - apiVersion: - type: string - default: margo.org - description: API version - kind: - type: string - default: ApplicationDeployment - description: Resource kind - metadata: - $ref: '#/components/schemas/appDeploymentMetadata' - spec: - $ref: '#/components/schemas/appDeploymentSpec' - appDeploymentMetadata: - type: object - required: [name] - properties: - id: - type: string - description: Unique identifier for the application deployment - name: - type: string - description: Name of the resource - namespace: - type: string - description: Namespace of the resource - labels: - type: object - additionalProperties: { type: string } - description: Labels for the resource - annotations: - type: object - additionalProperties: { type: string } - description: Annotations for the resource - helmApplicationDeploymentProfileComponent: - type: object - description: Helm Application Deployment Profile Component - required: [name, properties] - properties: - name: - type: string - description: Name of the component - properties: - type: object - required: [repository] - properties: - repository: - type: string - description: Repository of the component - revision: - type: string - description: Revision of the component - timeout: - type: string - description: Timeout for the component - wait: - type: boolean - description: Wait for the component to be ready - composeApplicationDeploymentProfileComponent: - type: object - description: Compose Application Deployment Profile Component - required: [name, properties] - properties: - name: - type: string - description: Name of the component - properties: - type: object - required: [packageLocation] - properties: - packageLocation: - type: string - description: Package location of the component - keyLocation: - type: string - description: Key location of the component - timeout: - type: string - description: Timeout for the component - wait: - type: boolean - description: Wait for the component to be ready - appDeploymentProfile: - type: object - description: Application Deployment Profile - required: [type, components] - properties: - type: - type: string - enum: ["helm.v3", "compose"] - description: Type of deployment profile - components: - type: array - items: - oneOf: - - $ref: '#/components/schemas/helmApplicationDeploymentProfileComponent' - - $ref: '#/components/schemas/composeApplicationDeploymentProfileComponent' - description: Components of the deployment profile - appParameterTarget: - type: object - description: Application Parameter Target - required: [pointer, components] - properties: - pointer: - type: string - description: Pointer to the parameter - components: - type: array - items: - type: string - description: Components of the parameter - appParameterValue: - type: object - description: Application Parameter Value - required: [value, targets] - properties: - value: - # type: object - description: Value of the parameter - additionalProperties: true - x-go-type: interface{} - targets: - type: array - items: - $ref: '#/components/schemas/appParameterTarget' - description: Targets of the parameter - appDeploymentParams: - type: object - description: Application Parameters - additionalProperties: - $ref: '#/components/schemas/appParameterValue' - appDeploymentSpec: - type: object - description: Application Deployment specification - required: [appPackageRef, deploymentProfile] - properties: - deploymentProfile: - $ref: '#/components/schemas/appDeploymentProfile' - description: Deployment profile - parameters: - $ref: '#/components/schemas/appDeploymentParams' - description: Parameters for the deployment \ No newline at end of file diff --git a/scripts/sync-general-content.sh b/scripts/sync-general-content.sh index 622c3a2..6c2422a 100755 --- a/scripts/sync-general-content.sh +++ b/scripts/sync-general-content.sh @@ -136,7 +136,7 @@ done echo "Generating SwaggerUI MDX files..." rm -f "$ROOT_DIR/content/docs/specification/margo-management-interface/management-interface-swagger.md" -find "$ROOT_DIR/content/docs" -type f \( -name "workload-management-api-1.0.0.yaml" -o -name "workload-management-api-1.0.0.yml" \) -print0 | while IFS= read -r -d '' yaml; do +find "$ROOT_DIR/content/docs" -type f \( -name "workload-management-api-*.yaml" -o -name "workload-management-api-*.yml" \) -print0 | while IFS= read -r -d '' yaml; do mdx="${yaml%.*}.mdx" base="$(basename "$yaml")" cat > "$mdx" <