From 4f88c8cff58af4d697f3c4b12b223748d2839434 Mon Sep 17 00:00:00 2001 From: nitparihar Date: Wed, 26 Aug 2026 05:11:54 +0000 Subject: [PATCH 1/2] Import multi-persona conformance toolkit from sandbox repo Moves the WFM Supplier and Application Supplier conformance test toolkit (runner, data generator, Postman/Newman collections, test cases) from margo/sandbox conformance/ into this dedicated repo, flattened to the repo root. Source: margo/sandbox @ 7bbf36b (branch feature/multi-persona-conformance) --- ARCHITECTURE.md | 1169 +++++++ Application-Supplier-Service/application.go | 760 ++++ Application-Supplier-Service/compose.go | 82 + Application-Supplier-Service/extractor.go | 88 + Application-Supplier-Service/helm.go | 48 + Application-Supplier-Service/main.go | 394 +++ Application-Supplier-Service/models.go | 69 + Application-Supplier-Service/report.go | 418 +++ Application-Supplier-Service/utils.go | 81 + Application-Supplier/margo-package/margo.yaml | 61 + .../margo-package/resources/description.md | 2 + .../margo-package/resources/license.txt | 2 + .../resources/opentelemtry-logo.png | 0 .../margo-package/resources/release-notes.md | 3 + .../device-supplier/.device-scenarios | 0 .../TestCases/test-scenarios.json | 1225 +++++++ .../device-supplier/assertions.json | 355 ++ .../device-supplier/assertions.json.bak | 354 ++ .../device-supplier/data/clients.json | 524 +++ .../device-supplier/data/deployments.json | 302 ++ .../device-supplier/deployment-template.yaml | 16 + .../device-supplier/groups/bronze/group.json | 71 + .../groups/bronze/test-scenarios.json | 1225 +++++++ .../device-supplier/groups/core/group.json | 11 + .../device-supplier/groups/diamond/group.json | 55 + .../groups/flex-order/group.json | 11 + .../device-supplier/groups/gold/group.json | 72 + .../groups/newgrp-devicesupplier1/group.json | 62 + .../device-supplier/groups/silver/group.json | 72 + .../device-supplier/test-scenarios.json | 1225 +++++++ Data-Generator/margo-test-gen.sh | 207 ++ Data-Generator/wfm-supplier/.functional-tests | 0 .../wfm-supplier/groups/bronze grp/group.json | 57 + .../groups/bronze grp/postman_collection.json | 2395 +++++++++++++ .../wfm-supplier/groups/core/group.json | 11 + .../wfm-supplier/groups/diamond/group.json | 102 + .../wfm-supplier/groups/seimens/group.json | 56 + .../wfm-supplier/groups/silver/group.json | 105 + .../groups/silver/postman_collection.json | 2417 +++++++++++++ .../vendor-negative-scenarios/group.json | 28 + .../postman_collection.json | 361 ++ .../vendor-positive-extended/group.json | 40 + .../postman_collection.json | 673 ++++ .../newman-data/certs/ca-cert.pem | 22 + .../newman-data/certs/device-cert.pem | 15 + .../wfm-supplier/newman-data/certs/device.key | 5 + .../newman-data/device-agent.env.json | 71 + .../newman-data/device-agent.iteration.json | 1 + .../wfm-supplier/newman-data/execution.log | 45 + .../newman-data/responses/bundle-details.json | 1 + .../responses/deployments-query.json | 1 + .../newman-data/responses/status-report.json | 1 + .../wfm-supplier/postman_collection.json | 2819 +++++++++++++++ .../postman_collection_functional.json | 2395 +++++++++++++ .../Hello World_04-08-2026_08-08-19.html | 678 ++++ ...mance-report-2026-06-30T04-43-20-000Z.html | 333 ++ ...mance-report-2026-06-30T04-51-30-000Z.html | 333 ++ ...mance-report-2026-07-30T11-38-25-000Z.html | 557 +++ ...mance-report-2026-08-03T08-09-28-000Z.html | 340 ++ ...mance-report-2026-08-04T08-46-12-000Z.html | 557 +++ ...mance-report-2026-08-17T08-42-43-000Z.html | 342 ++ ...mance-report-2026-08-17T08-42-55-000Z.html | 566 +++ ...mance-report-2026-08-17T08-42-59-000Z.html | 566 +++ ...mance-report-2026-08-17T08-43-03-000Z.html | 566 +++ ...mance-report-2026-08-17T08-43-47-000Z.html | 125 + ...mance-report-2026-08-17T08-44-44-000Z.html | 342 ++ ...mance-report-2026-08-17T08-44-48-000Z.html | 566 +++ ...mance-report-2026-08-17T12-52-09-000Z.html | 104 + Runner/device-supplier/test-execution.log | 45 + Runner/margo-test-run.sh | 310 ++ ...-scenario-report-core_20260817_125217.html | 153 + ...nario-report-silver-1_20260817_083730.html | 399 +++ ...nario-report-silver-1_20260817_083738.html | 399 +++ ...nario-report-silver-1_20260817_084449.html | 399 +++ ...nario-report-silver-1_20260817_084515.html | 399 +++ ...nario-report-silver-1_20260817_084810.html | 399 +++ client-demo-brief.md | 18 + conformance.sh | 1045 ++++++ conformance_cli.sh | 164 + demo.md | 179 + device-supplier/Final-Summary.md | 1227 +++++++ device-supplier/LICENSE | 21 + device-supplier/Makefile | 106 + device-supplier/README.md | 128 + device-supplier/bin/run_tests | Bin 0 -> 9631523 bytes device-supplier/bin/server | Bin 0 -> 10519470 bytes device-supplier/certs/ca-cert.pem | 22 + device-supplier/certs/ca-cert.srl | 1 + device-supplier/certs/ca-key.pem | 28 + device-supplier/certs/device-cert.pem | 22 + device-supplier/certs/device-key.pem | 28 + device-supplier/certs/server-cert.pem | 23 + device-supplier/certs/server-key.pem | 28 + device-supplier/cmd/device-supplier/main.go | 1747 ++++++++++ device-supplier/conformance-test-run.log | 106 + device-supplier/data/clients.json | 51 + device-supplier/data/deployments.json | 12 + .../device-scenarios/CUSTOM_TEMPLATE_GUIDE.md | 362 ++ .../TEMPLATE_custom_test_scenario.json | 394 +++ .../device-scenarios/test-scenarios.json | 350 ++ .../vendor-extended-scenarios.json | 1125 ++++++ .../docs/ARCHITECTURE_FIX_SUMMARY.md | 179 + .../docs/CERTIFICATE_ARCHITECTURE.md | 265 ++ .../docs/CERTIFICATE_GENERATION.md | 296 ++ device-supplier/docs/FIX_EXPLANATION.md | 152 + device-supplier/docs/template.md | 1 + device-supplier/generate-certs.sh | 156 + device-supplier/go.mod | 16 + device-supplier/go.sum | 20 + device-supplier/manifests/assertions.json | 377 ++ device-supplier/manifests/assertions.json.bak | 354 ++ .../manifests/deployment-template-app-a.yaml | 16 + .../manifests/deployment-template-app-b.yaml | 16 + .../manifests/deployment-template.yaml | 16 + ...mance-report-2026-06-23T10-09-52-000Z.html | 326 ++ ...mance-report-2026-06-23T10-10-25-000Z.html | 326 ++ ...mance-report-2026-06-30T04-43-20-000Z.html | 333 ++ ...mance-report-2026-06-30T04-51-30-000Z.html | 333 ++ ...mance-report-2026-07-07T06-47-13-000Z.html | 333 ++ ...mance-report-2026-07-30T11-38-25-000Z.html | 557 +++ ...mance-report-2026-08-03T08-09-28-000Z.html | 340 ++ ...mance-report-2026-08-04T08-46-12-000Z.html | 557 +++ ...mance-report-2026-08-17T08-43-03-000Z.html | 566 +++ ...mance-report-2026-08-17T08-43-47-000Z.html | 125 + ...mance-report-2026-08-17T08-44-44-000Z.html | 342 ++ ...mance-report-2026-08-17T08-44-48-000Z.html | 566 +++ ...mance-report-2026-08-17T12-51-22-000Z.html | 104 + ...mance-report-2026-08-17T12-52-09-000Z.html | 104 + device-supplier/run_tests.go | 798 +++++ device-supplier/run_tests.go.bak | 659 ++++ .../sample-apps/app-a/compose.yaml | 8 + .../sample-apps/app-b/compose.yaml | 8 + manual-test-cases/README.md | 96 + .../postman_collection_sample.json | 2395 +++++++++++++ run-tests.sh | 1909 +++++++++++ run-tests.sh.bak | 1152 +++++++ test_device.sh | 9 + testcases/device-core/core.json | 245 ++ .../bundle.json | 100 + .../capabilities.json | 512 +++ .../certificate.json | 28 + .../deployment-manifest.json | 107 + .../desired-state.json | 937 +++++ .../onboarding.json | 181 + .../status.json | 238 ++ testcases/user1/postman_collection.json | 2395 +++++++++++++ testcases/user2/test-scenario.json | 2395 +++++++++++++ testcases/user2Device/test-scenarios.json | 1306 +++++++ testcases/wfm-core/core.json | 179 + wfm-supplier/.collection.runtime.json | 2432 +++++++++++++ wfm-supplier/1-setup_portman.sh | 253 ++ wfm-supplier/2-run_newman.sh | 343 ++ wfm-supplier/3-execute-workloads.sh | 543 +++ wfm-supplier/4-cleanup.sh | 87 + wfm-supplier/DEMO_GUIDE.md | 147 + wfm-supplier/README.md | 538 +++ wfm-supplier/certs/ca-cert.pem | 22 + wfm-supplier/multi-app-desired-state.json | 240 ++ wfm-supplier/newman-data/certs/ca-cert.pem | 22 + .../newman-data/certs/device-cert.pem | 15 + wfm-supplier/newman-data/certs/device.key | 5 + .../newman-data/device-agent.env.json | 71 + .../newman-data/device-agent.iteration.json | 1 + wfm-supplier/newman-data/execution.log | 45 + .../newman-data/responses/bundle-details.json | 1 + .../responses/deployments-query.json | 1 + .../newman-data/responses/status-report.json | 1 + wfm-supplier/patch_postman_collection.jq | 53 + wfm-supplier/postman_collection.json | 2819 +++++++++++++++ wfm-supplier/quick-start.md | 196 ++ wfm-supplier/run.sh | 72 + wfm-supplier/run_wfm_scenarios.js | 1166 +++++++ wfm-supplier/run_wfm_scenarios.js.bak | 774 +++++ wfm-supplier/spec.yaml | 811 +++++ wfm-supplier/summary.md | 719 ++++ wfm-supplier/tmp/working/tmpCollection.json | 2586 ++++++++++++++ .../wfm-test-report-gold_20260616_105021.html | 3042 +++++++++++++++++ .../wfm-test-report-gold_20260616_121434.html | 3042 +++++++++++++++++ .../wfm-test-report-gold_20260617_061726.html | 3042 +++++++++++++++++ 179 files changed, 81772 insertions(+) create mode 100644 ARCHITECTURE.md create mode 100644 Application-Supplier-Service/application.go create mode 100644 Application-Supplier-Service/compose.go create mode 100644 Application-Supplier-Service/extractor.go create mode 100644 Application-Supplier-Service/helm.go create mode 100644 Application-Supplier-Service/main.go create mode 100644 Application-Supplier-Service/models.go create mode 100644 Application-Supplier-Service/report.go create mode 100644 Application-Supplier-Service/utils.go create mode 100644 Application-Supplier/margo-package/margo.yaml create mode 100644 Application-Supplier/margo-package/resources/description.md create mode 100644 Application-Supplier/margo-package/resources/license.txt create mode 100644 Application-Supplier/margo-package/resources/opentelemtry-logo.png create mode 100644 Application-Supplier/margo-package/resources/release-notes.md create mode 100644 Data-Generator/device-supplier/.device-scenarios create mode 100644 Data-Generator/device-supplier/TestCases/test-scenarios.json create mode 100644 Data-Generator/device-supplier/assertions.json create mode 100644 Data-Generator/device-supplier/assertions.json.bak create mode 100644 Data-Generator/device-supplier/data/clients.json create mode 100644 Data-Generator/device-supplier/data/deployments.json create mode 100644 Data-Generator/device-supplier/deployment-template.yaml create mode 100644 Data-Generator/device-supplier/groups/bronze/group.json create mode 100644 Data-Generator/device-supplier/groups/bronze/test-scenarios.json create mode 100644 Data-Generator/device-supplier/groups/core/group.json create mode 100644 Data-Generator/device-supplier/groups/diamond/group.json create mode 100644 Data-Generator/device-supplier/groups/flex-order/group.json create mode 100644 Data-Generator/device-supplier/groups/gold/group.json create mode 100644 Data-Generator/device-supplier/groups/newgrp-devicesupplier1/group.json create mode 100644 Data-Generator/device-supplier/groups/silver/group.json create mode 100644 Data-Generator/device-supplier/test-scenarios.json create mode 100755 Data-Generator/margo-test-gen.sh create mode 100644 Data-Generator/wfm-supplier/.functional-tests create mode 100644 Data-Generator/wfm-supplier/groups/bronze grp/group.json create mode 100644 Data-Generator/wfm-supplier/groups/bronze grp/postman_collection.json create mode 100644 Data-Generator/wfm-supplier/groups/core/group.json create mode 100644 Data-Generator/wfm-supplier/groups/diamond/group.json create mode 100644 Data-Generator/wfm-supplier/groups/seimens/group.json create mode 100644 Data-Generator/wfm-supplier/groups/silver/group.json create mode 100644 Data-Generator/wfm-supplier/groups/silver/postman_collection.json create mode 100644 Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/group.json create mode 100644 Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/postman_collection.json create mode 100644 Data-Generator/wfm-supplier/groups/vendor-positive-extended/group.json create mode 100644 Data-Generator/wfm-supplier/groups/vendor-positive-extended/postman_collection.json create mode 100644 Data-Generator/wfm-supplier/newman-data/certs/ca-cert.pem create mode 100644 Data-Generator/wfm-supplier/newman-data/certs/device-cert.pem create mode 100644 Data-Generator/wfm-supplier/newman-data/certs/device.key create mode 100644 Data-Generator/wfm-supplier/newman-data/device-agent.env.json create mode 100644 Data-Generator/wfm-supplier/newman-data/device-agent.iteration.json create mode 100644 Data-Generator/wfm-supplier/newman-data/execution.log create mode 100644 Data-Generator/wfm-supplier/newman-data/responses/bundle-details.json create mode 100644 Data-Generator/wfm-supplier/newman-data/responses/deployments-query.json create mode 100644 Data-Generator/wfm-supplier/newman-data/responses/status-report.json create mode 100644 Data-Generator/wfm-supplier/postman_collection.json create mode 100644 Data-Generator/wfm-supplier/postman_collection_functional.json create mode 100644 Runner/application-supplier/Hello World_04-08-2026_08-08-19.html create mode 100644 Runner/device-supplier/conformance-report-2026-06-30T04-43-20-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-06-30T04-51-30-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-07-30T11-38-25-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-03T08-09-28-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-04T08-46-12-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-42-43-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-42-55-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-42-59-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-43-03-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-43-47-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-44-44-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T08-44-48-000Z.html create mode 100644 Runner/device-supplier/conformance-report-2026-08-17T12-52-09-000Z.html create mode 100644 Runner/device-supplier/test-execution.log create mode 100755 Runner/margo-test-run.sh create mode 100644 Runner/wfm-supplier/wfm-scenario-report-core_20260817_125217.html create mode 100644 Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083730.html create mode 100644 Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083738.html create mode 100644 Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084449.html create mode 100644 Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084515.html create mode 100644 Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084810.html create mode 100644 client-demo-brief.md create mode 100755 conformance.sh create mode 100755 conformance_cli.sh create mode 100644 demo.md create mode 100644 device-supplier/Final-Summary.md create mode 100644 device-supplier/LICENSE create mode 100644 device-supplier/Makefile create mode 100644 device-supplier/README.md create mode 100755 device-supplier/bin/run_tests create mode 100755 device-supplier/bin/server create mode 100644 device-supplier/certs/ca-cert.pem create mode 100644 device-supplier/certs/ca-cert.srl create mode 100644 device-supplier/certs/ca-key.pem create mode 100644 device-supplier/certs/device-cert.pem create mode 100644 device-supplier/certs/device-key.pem create mode 100644 device-supplier/certs/server-cert.pem create mode 100644 device-supplier/certs/server-key.pem create mode 100644 device-supplier/cmd/device-supplier/main.go create mode 100644 device-supplier/conformance-test-run.log create mode 100644 device-supplier/data/clients.json create mode 100644 device-supplier/data/deployments.json create mode 100644 device-supplier/device-scenarios/CUSTOM_TEMPLATE_GUIDE.md create mode 100644 device-supplier/device-scenarios/TEMPLATE_custom_test_scenario.json create mode 100644 device-supplier/device-scenarios/test-scenarios.json create mode 100644 device-supplier/device-scenarios/vendor-extended-scenarios.json create mode 100644 device-supplier/docs/ARCHITECTURE_FIX_SUMMARY.md create mode 100644 device-supplier/docs/CERTIFICATE_ARCHITECTURE.md create mode 100644 device-supplier/docs/CERTIFICATE_GENERATION.md create mode 100644 device-supplier/docs/FIX_EXPLANATION.md create mode 100644 device-supplier/docs/template.md create mode 100755 device-supplier/generate-certs.sh create mode 100644 device-supplier/go.mod create mode 100644 device-supplier/go.sum create mode 100644 device-supplier/manifests/assertions.json create mode 100644 device-supplier/manifests/assertions.json.bak create mode 100644 device-supplier/manifests/deployment-template-app-a.yaml create mode 100644 device-supplier/manifests/deployment-template-app-b.yaml create mode 100644 device-supplier/manifests/deployment-template.yaml create mode 100644 device-supplier/reports/conformance-report-2026-06-23T10-09-52-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-06-23T10-10-25-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-06-30T04-43-20-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-06-30T04-51-30-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-07-07T06-47-13-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-07-30T11-38-25-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-03T08-09-28-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-04T08-46-12-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T08-43-03-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T08-43-47-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T08-44-44-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T08-44-48-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T12-51-22-000Z.html create mode 100644 device-supplier/reports/conformance-report-2026-08-17T12-52-09-000Z.html create mode 100644 device-supplier/run_tests.go create mode 100644 device-supplier/run_tests.go.bak create mode 100644 device-supplier/sample-apps/app-a/compose.yaml create mode 100644 device-supplier/sample-apps/app-b/compose.yaml create mode 100644 manual-test-cases/README.md create mode 100644 manual-test-cases/postman_collection_sample.json create mode 100755 run-tests.sh create mode 100755 run-tests.sh.bak create mode 100755 test_device.sh create mode 100644 testcases/device-core/core.json create mode 100644 testcases/device-supplier-flexible-order/bundle.json create mode 100644 testcases/device-supplier-flexible-order/capabilities.json create mode 100644 testcases/device-supplier-flexible-order/certificate.json create mode 100644 testcases/device-supplier-flexible-order/deployment-manifest.json create mode 100644 testcases/device-supplier-flexible-order/desired-state.json create mode 100644 testcases/device-supplier-flexible-order/onboarding.json create mode 100644 testcases/device-supplier-flexible-order/status.json create mode 100644 testcases/user1/postman_collection.json create mode 100644 testcases/user2/test-scenario.json create mode 100644 testcases/user2Device/test-scenarios.json create mode 100644 testcases/wfm-core/core.json create mode 100644 wfm-supplier/.collection.runtime.json create mode 100755 wfm-supplier/1-setup_portman.sh create mode 100644 wfm-supplier/2-run_newman.sh create mode 100755 wfm-supplier/3-execute-workloads.sh create mode 100755 wfm-supplier/4-cleanup.sh create mode 100644 wfm-supplier/DEMO_GUIDE.md create mode 100644 wfm-supplier/README.md create mode 100644 wfm-supplier/certs/ca-cert.pem create mode 100644 wfm-supplier/multi-app-desired-state.json create mode 100644 wfm-supplier/newman-data/certs/ca-cert.pem create mode 100644 wfm-supplier/newman-data/certs/device-cert.pem create mode 100644 wfm-supplier/newman-data/certs/device.key create mode 100644 wfm-supplier/newman-data/device-agent.env.json create mode 100644 wfm-supplier/newman-data/device-agent.iteration.json create mode 100644 wfm-supplier/newman-data/execution.log create mode 100644 wfm-supplier/newman-data/responses/bundle-details.json create mode 100644 wfm-supplier/newman-data/responses/deployments-query.json create mode 100644 wfm-supplier/newman-data/responses/status-report.json create mode 100644 wfm-supplier/patch_postman_collection.jq create mode 100644 wfm-supplier/postman_collection.json create mode 100644 wfm-supplier/quick-start.md create mode 100755 wfm-supplier/run.sh create mode 100644 wfm-supplier/run_wfm_scenarios.js create mode 100644 wfm-supplier/run_wfm_scenarios.js.bak create mode 100644 wfm-supplier/spec.yaml create mode 100644 wfm-supplier/summary.md create mode 100644 wfm-supplier/tmp/working/tmpCollection.json create mode 100644 wfm-supplier/wfm-test-report-gold_20260616_105021.html create mode 100644 wfm-supplier/wfm-test-report-gold_20260616_121434.html create mode 100644 wfm-supplier/wfm-test-report-gold_20260617_061726.html diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..27825c0 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,1169 @@ +# Margo Conformance Testing — Architecture, Implementation & Troubleshooting Guide + +**Last updated:** 2026-06-17 +**Spec reference:** [Margo Management Interface — workload-management-api-1.0.0](https://raw.githubusercontent.com/margo/specification/pre-draft/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml) +**Verified against:** Symphony WFM at `https://symphony.machine:8082/v1alpha2/margo` + +--- + +## Table of Contents + +1. [What Is This Conformance Suite?](#1-what-is-this-conformance-suite) +2. [System Architecture Overview](#2-system-architecture-overview) +3. [Two Personas Explained](#3-two-personas-explained) +4. [Directory Structure](#4-directory-structure) +5. [How to Run Tests](#5-how-to-run-tests) +6. [The Margo WFM API — Endpoint Reference](#6-the-margo-wfm-api--endpoint-reference) +7. [HTTP Message Signatures (RFC 9421) — Deep Dive](#7-http-message-signatures-rfc-9421--deep-dive) +8. [Real WFM Behavior vs Spec (Important Differences)](#8-real-wfm-behavior-vs-spec-important-differences) +9. [The Node.js Scenario Runner — How It Works](#9-the-nodejs-scenario-runner--how-it-works) +10. [Test Scenario JSON Format (Custom Adapter Format)](#10-test-scenario-json-format-custom-adapter-format) +11. [Group System — How Groups Work](#11-group-system--how-groups-work) +12. [Common Errors and How to Fix Them](#12-common-errors-and-how-to-fix-them) +13. [Certificate Lifecycle](#13-certificate-lifecycle) +14. [How the Real Device-Agent Works](#14-how-the-real-device-agent-works) +15. [Design Notes — Postman vs Custom Format](#15-design-notes--postman-vs-custom-format) +16. [Adding or Modifying Tests](#16-adding-or-modifying-tests) + +--- + +## 1. What Is This Conformance Suite? + +The Margo Conformance Suite is built for **Margo specification authors and members** to verify that a real WFM (Workload Fleet Manager) or a real Device Agent correctly implements the [Margo Management Interface specification](https://raw.githubusercontent.com/margo/specification/pre-draft/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml). + +**The use case:** A Margo member brings their WFM implementation (e.g., Symphony) or their device-agent implementation and runs the conformance suite against it. At the end, they get a signed test report showing which parts of the Margo spec their implementation conforms to. + +The system has two CLIs: + +``` +conformance.sh → Prepare: create test groups, configure data, select test IDs +run-tests.sh → Execute: run tests against real WFM or device, generate reports +``` + +**Important:** The test scenarios (what to test and how) are created by the Margo user — typically exported from Postman as a collection. The conformance infrastructure handles running them, signing requests with RFC 9421, and generating a group-based report. See [Section 15](#15-design-notes--postman-vs-custom-format) for why there is also a custom JSON format. + +--- + +## 2. System Architecture Overview + +``` +┌──────────────────────────────────────────────────────────────────────┐ +│ MARGO CONFORMANCE SYSTEM │ +│ │ +│ conformance.sh (CLI #1) run-tests.sh (CLI #2) │ +│ ┌──────────────────────┐ ┌──────────────────────────────┐ │ +│ │ Prepare │ │ Execute │ │ +│ │ - Create groups │────────▶│ │ │ +│ │ - Collect test IDs │ │ WFM Supplier persona │ │ +│ │ from scenario files│ │ ┌──────────────────────┐ │ │ +│ │ - Generate group.json│ │ │ Scenario JSON files │ │ │ +│ │ - Generate certs │ │ │ → run_wfm_scenarios.js│ │ │ +│ └──────────────────────┘ │ │ (Node.js, RFC 9421 │ │ │ +│ │ │ signing, hits WFM) │ │ │ +│ │ └──────────────────────┘ │ │ +│ │ OR │ │ +│ │ ┌──────────────────────┐ │ │ +│ │ │ Postman collections │ │ │ +│ │ │ → Newman runner │ │ │ +│ │ └──────────────────────┘ │ │ +│ │ │ │ +│ │ Device Supplier persona │ │ +│ │ ┌──────────────────────┐ │ │ +│ │ │ run_tests.go │ │ │ +│ │ │ (Go, mock WFM, │ │ │ +│ │ │ tests real device) │ │ │ +│ │ └──────────────────────┘ │ │ +│ └──────────────────────────────┘ │ +│ │ │ +│ HTML Reports per Group │ +│ Runner/wfm-supplier/*.html │ +└──────────────────────────────────────────────────────────────────────┘ +``` + +### Component roles + +| Component | Language | Role | +|-----------|----------|------| +| `conformance.sh` | Bash | Interactive setup: create groups, collect test IDs from scenario files, generate `group.json` | +| `run-tests.sh` | Bash | Orchestrator: selects persona/group, calls the right runner, generates reports | +| `run_wfm_scenarios.js` | Node.js | WFM Supplier runner when scenario files use the custom format (handles RFC 9421 signing) | +| Newman | npm | WFM Supplier runner when scenario files are Postman collections | +| `run_tests.go` | Go | Device Supplier runner: starts a mock WFM, tests a real device agent | + +--- + +## 3. Two Personas Explained + +### WFM Supplier + +> "I am building a WFM. Test it against the Margo spec." + +The WFM Supplier persona verifies that a **WFM implementation** correctly implements the Margo specification. + +The conformance tool **acts as a conformant device** and sends all kinds of requests to the **real WFM under test** — valid requests, invalid requests, edge cases, negative tests. It checks that the WFM returns the correct responses, HTTP status codes, headers, and error formats. + +``` +Conformance Tool (acts as device) ───────▶ Real WFM (under test) + run_wfm_scenarios.js symphony.machine:8082 + ─ Signs requests with RFC 9421 /v1alpha2/margo + ─ Sends onboarding, capabilities, + deployment retrieval, status updates + ─ Validates responses against spec +``` + +**Who uses this:** WFM vendors, Margo spec authors testing a WFM implementation. + +### Device Supplier + +> "I am building a device agent. Test it against the Margo spec." + +The Device Supplier persona verifies that a **device agent implementation** correctly communicates with a WFM. + +The conformance tool **acts as a mock WFM** and accepts connections from a real device agent. It checks that the device makes the right API calls, sends correctly-signed requests, and handles deployment instructions correctly. + +``` +Conformance Tool (acts as WFM) ◀────── Real Device Agent (under test) + run_tests.go device-agent binary + ─ Provides mock WFM endpoints + ─ Validates what device sends + ─ Returns test deployment instructions +``` + +**Who uses this:** Device vendors, Margo spec authors testing a device implementation. + +--- + +## 4. Directory Structure + +``` +conformance/ +├── conformance.sh # CLI #1: interactive group setup +├── run-tests.sh # CLI #2: test execution +│ +├── wfm-supplier/ # WFM Supplier persona +│ ├── run_wfm_scenarios.js # ★ Custom-format scenario runner (RFC 9421 signing) +│ ├── run_wfm_scenarios.js.bak # Backup copy +│ ├── spec.yaml # Local copy of the Margo WFM OpenAPI spec +│ ├── postman_collection.json # Legacy Postman collection (Newman path) +│ └── newman-data/ +│ ├── certs/ # ★ Active certificate directory (used at runtime) +│ │ ├── device.key # Fresh ECDSA P-256 private key (regenerated per scenario) +│ │ ├── device-cert.pem # Fresh self-signed certificate +│ │ └── ca-cert.pem # WFM's CA cert (copy from symphony after start) +│ └── device-agent.env.json # Postman/Newman environment variables +│ +├── Data-Generator/ +│ └── wfm-supplier/ +│ └── groups/ +│ ├── diamond/ # Test group "diamond" +│ │ ├── group.json # ★ Which test IDs to run (generated by conformance.sh) +│ │ └── test-scenarios.json # ★ Scenario definitions (user-provided) +│ └── silver/ # Another test group (example) +│ ├── group.json +│ └── ... +│ +└── Runner/ + └── wfm-supplier/ # HTML reports (one per run) + └── wfm-scenario-report-diamond_YYYYMMDD_HHMMSS.html +``` + +--- + +## 5. How to Run Tests + +### Prerequisites + +1. Real WFM (Symphony) must be running at `https://symphony.machine:8082` +2. CA certificate copied: `conformance/wfm-supplier/newman-data/certs/ca-cert.pem` +3. Node.js installed (v13.2+ for `dsaEncoding: 'ieee-p1363'` support) + +### Getting the CA certificate + +```bash +# Restart Symphony to clear previously-registered device certs (avoids 409 on re-onboarding) +# Use the wfm.sh menu: press 4 (stop) then 3 (start) + +# Copy the CA cert +cp ~/symphony/api/certs/ca-cert.pem \ + ~/nitin/sandbox/conformance/wfm-supplier/newman-data/certs/ca-cert.pem +``` + +### Running the tests + +```bash +cd ~/nitin/sandbox/conformance + +# Interactive mode (prompts for persona, group, URL): +./run-tests.sh + +# Direct mode: +./run-tests.sh wfm diamond https://symphony.machine:8082/v1alpha2/margo +``` + +**Arguments:** +- `wfm` — WFM Supplier persona +- `diamond` — test group name +- URL — full WFM base URL (must include `/v1alpha2/margo`) + +### What happens during a run + +1. `run-tests.sh` reads `group.json` for the selected group +2. It reads all `test-scenarios.json` files in the group directory +3. `jq` filters the scenarios: only steps whose IDs appear in `group.json` → `testCases` are included +4. A **fresh ECDSA P-256 certificate** is generated via `openssl` +5. `node run_wfm_scenarios.js` is called with the filtered scenario list +6. The runner executes each scenario (regenerating a fresh cert per scenario to avoid 409) +7. An HTML report is written to `Runner/wfm-supplier/` + +### Example output + +``` +════════════════════════════════════════════════════════════════════════ + Margo WFM Conformance Test Runner + WFM Scenario Test + WFM: https://symphony.machine:8082/v1alpha2/margo +════════════════════════════════════════════════════════════════════════ + +──────────────────────────────────────────────────────────────────────── + SCENARIO 5 of 7 · Device Onboarding + Certificate retrieval plus successful and rejected onboarding flows. +──────────────────────────────────────────────────────────────────────── + + [step-1.1] Get Root CA Certificate + ▶ GET /api/v1/onboarding/certificate [signed] + ✓ PASS 200 OK + + [step-1.2] Onboard Trusted Device + ▶ POST /api/v1/onboarding [signed · content-digest] + ✓ PASS 201 Created + ↳ clientId = "client-f10ec980a73cbc76-1781705938" + + [step-1.3] Reject Duplicate Certificate Registration + ▶ POST /api/v1/onboarding [signed · content-digest] + ✓ PASS 409 Conflict + + Scenario result: 3/3 steps ✓ all passed +... +════════════════════════════════════════════════════════════════════════ + CONFORMANCE SUMMARY · 38 tests +════════════════════════════════════════════════════════════════════════ + + Scenario Steps Passed Failed + ─────────────────────────────────────────────────────────── + Capabilities Reporting 3 3 0 + Capabilities Error Handling 8 8 0 + Deployment Retrieval And Status 3 3 0 + Capabilities With Missing ApiVersion 2 2 0 + Device Onboarding 3 3 0 + Onboarding Error Handling 6 6 0 + Status And Retrieval Errors 13 13 0 + ─────────────────────────────────────────────────────────── + TOTAL 38 38 0 + + ✅ ALL 38 TESTS PASSED +════════════════════════════════════════════════════════════════════════ +``` + +--- + +## 6. The Margo WFM API — Endpoint Reference + +All paths are relative to the WFM base URL. The Symphony implementation uses the internal path prefix `/api/v1/` for all endpoints. + +### GET `/api/v1/onboarding/certificate` + +Returns the WFM's root CA certificate. **No signature required.** + +**Response 200:** +```json +{ "certificate": "LS0tLS1CRUd..." } // Base64-encoded PEM +``` + +--- + +### POST `/api/v1/onboarding` + +Registers a new device. **Signature is optional** — the device certificate itself is the identity. + +**Request body:** +```json +{ + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "" +} +``` + +The runner injects the base64-encoded `device-cert.pem` content when the scenario step contains `"certificate": "./certs/device-cert.pem"`. + +**Response 201:** +```json +{ "clientId": "client-a74b314d0fb61bd5-1781702233" } +``` + +**CRITICAL:** Save `clientId`. It is used as the URL path parameter for every subsequent API call, AND must appear in `properties.id` in capability manifests. + +**Response 409:** Same cert already registered: +```json +{ "Error": "Device signature already exists" } +``` + +**Response 400:** Schema validation failure: +```json +{ "Error": "invalid API version: v1" } +``` + +**What the WFM validates at onboarding:** +- `apiVersion` must be `"onboarding.margo.org/v1alpha1"` (returns 400: "API version") +- `kind` must be `"OnboardingRequest"` (returns 400: "kind") +- `certificate` must be present and non-empty (returns 400: "certificate") +- **Does NOT validate** that the certificate is signed by a trusted CA — any cert is accepted + +--- + +### POST `/api/v1/clients/{clientId}/capabilities` +### PUT `/api/v1/clients/{clientId}/capabilities` + +Reports device capabilities. **Signature required.** + +**Request body:** +```json +{ + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "client-a74b314d0fb61bd5-1781702233", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "arm64" }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } +} +``` + +**CRITICAL RULE:** `properties.id` **MUST equal** the `clientId` from onboarding. If they differ: +```json +{ "Error": "device ID mismatch" } ← HTTP 400 +``` + +In scenario JSON always use `"id": "{clientId}"` so it gets substituted with the real value. + +**Response 201:** +```json +{ "message": "Device capabilities reported successfully" } +``` + +**What the WFM validates:** +| Field | Validates? | On failure | +|-------|-----------|------------| +| `properties.id` vs URL `clientId` | ✅ Yes | 400 "device ID" | +| `apiVersion` | ✅ Yes | 400 | +| `kind` | ✅ Yes | 400 | +| `roles` values | ❌ No | 201 (accepted) | +| `interfaces[].type` values | ❌ No | 201 (accepted) | +| `cpu.architecture` values | ❌ No | 201 (accepted) | + +--- + +### GET `/api/v1/clients/{clientId}/deployments` + +Returns the current desired-state manifest. **Signature required.** + +**Required header:** `Accept: application/vnd.margo.manifest.v1+json` + +**Response 200:** +```json +{ + "manifestVersion": 1, + "bundle": null, + "deployments": [] +} +``` + +**Response headers:** +``` +ETag: "sha256:abc123..." +``` + +Use the ETag with `If-None-Match` on the next request to get 304 if unchanged. + +**Response 304:** Manifest unchanged (no body). +**Response 500:** Wrong `Accept` header (spec says 406, real WFM returns 500): +```json +{ "Error": "accept header not supported" } +``` + +--- + +### GET `/api/v1/clients/{clientId}/bundles/{digest}` + +Downloads the deployment bundle archive. **Signature required.** + +`digest` is content-addressable (e.g., `sha256:abcdef...`). If the digest does not match stored content → 404. + +**Response 200 headers:** +``` +Content-Type: application/vnd.margo.bundle.v1+tar+gzip +Cache-Control: public, max-age=31536000, immutable +ETag: "" +``` + +**Response 401:** No signature (GET resource endpoints return 401, not 400). + +--- + +### GET `/api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}` + +Downloads a single deployment YAML file. **Signature required.** + +**Response 200 headers:** +``` +Content-Type: application/yaml +Cache-Control: public, max-age=31536000, immutable +Vary: Accept-Encoding +ETag: "" +``` + +**Response 401:** No signature. + +--- + +### POST `/api/v1/clients/{clientId}/deployments/{deploymentId}/status` + +Reports deployment status. **Signature required.** + +**Request body:** +```json +{ + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "dep-abc123", + "status": { "state": "installed" }, + "components": [{ "name": "app-component-1", "state": "installed" }] +} +``` + +`deploymentId` in the body **must match** the `{deploymentId}` in the URL. + +**Valid `state` values:** `installed`, `installing`, `uninstalling`, `failed` + +**Response 200:** +```json +{ "acknowledgement": "received" } +``` + +--- + +## 7. HTTP Message Signatures (RFC 9421) — Deep Dive + +Every WFM API request (except `GET /onboarding/certificate`) must be signed. This is the most complex and error-prone part. Read this section carefully if you encounter 400 errors. + +### What gets signed + +**Requests without a body (GET, DELETE):** +``` +"@method": GET +"@target-uri": https://symphony.machine:8082/v1alpha2/margo/api/v1/clients/abc/deployments +"@authority": symphony.machine:8082 +"@signature-params": ("@method" "@target-uri" "@authority");created=1718600000;keyid="a1b2c3..." +``` + +**Requests with a body (POST, PUT):** +``` +"@method": POST +"@target-uri": https://symphony.machine:8082/v1alpha2/margo/api/v1/clients/abc/capabilities +"@authority": symphony.machine:8082 +"content-digest": sha-256=:BASE64HASH: +"@signature-params": ("@method" "@target-uri" "@authority" "content-digest");created=1718600000;keyid="a1b2c3..." +``` + +**CRITICAL:** `@authority` is `host:port` (e.g., `symphony.machine:8082`). The WFM verifier (`shared-lib/crypto/verifier.go`) uses `htmsighttp.WithComponents(Method, TargetURI, Authority)` and **requires** all three. Requests missing `@authority` in their signature are silently rejected. + +### Produced HTTP headers + +``` +Content-Digest: sha-256=:BASE64==: +Signature-Input: sig1=("@method" "@target-uri" "@authority" "content-digest");created=1718600000;keyid="abc123..." +Signature: sig1=:BASE64SIGNATURE: +``` + +### Key ID (`keyid`) + +The `keyid` tells the WFM which registered public key to use for verification. It must match the algorithm used by `shared-lib/crypto/keyid.go::ComputeKeyIDFromPrivateKeyPEM`: + +``` +keyid = hex( SHA-256( PKIX-DER-encoded-public-key ) ) +``` + +Step by step: +1. Load ECDSA private key from PEM +2. Derive the public key +3. Marshal to PKIX DER format (`x509.MarshalPKIXPublicKey`) +4. SHA-256 hash the DER bytes +5. Hex-encode the hash + +**In Node.js:** +```javascript +function computeKeyId(privateKeyPem) { + const privObj = crypto.createPrivateKey(privateKeyPem); + const pubDer = crypto.createPublicKey(privObj).export({ format: 'der', type: 'spki' }); + return crypto.createHash('sha256').update(pubDer).digest('hex'); +} +``` + +**Wrong approaches:** Hardcoding `"device-key"`, using the cert fingerprint in a different format, using the raw public key bytes before PKIX wrapping. + +### ECDSA signature format — the most common bug + +The Margo Go verifier (`lestrrat-go/dsig`) uses **IEEE P1363 format** (raw r||s): +- For P-256: exactly **64 bytes** (32 r + 32 s) + +Node.js `createSign().sign()` produces **DER/ASN.1 format** by default: +- For P-256: approximately **70–72 bytes** (variable, ASN.1 wrapping) + +The verifier does `if len(signature) != keySize*2 { reject }` — DER-encoded signatures are always rejected with no useful error. + +**Wrong (DER, ~70 bytes — DO NOT USE):** +```javascript +const signer = crypto.createSign('sha256'); +signer.update(signatureInput); +const sig = signer.sign(privateKey); // ← Wrong format +``` + +**Correct (IEEE P1363, exactly 64 bytes for P-256):** +```javascript +const signatureBytes = crypto.sign('sha256', Buffer.from(signatureInput), { + key: privateKey, + dsaEncoding: 'ieee-p1363', // ← Required +}); +``` + +`dsaEncoding: 'ieee-p1363'` requires Node.js v13.2+. + +### Content-Digest (RFC 9530) + +Format: `sha-256=:BASE64:` — colons wrap the base64 value. + +```javascript +const digest = crypto.createHash('sha256').update(bodyText).digest('base64'); +headers['Content-Digest'] = `sha-256=:${digest}:`; +``` + +**Important ordering:** Content-Digest must be computed and set in headers **before** signing, because the signature covers the `content-digest` header value. The runner calls `prepareContentDigest()` before `signRequest()`. + +**Important:** WFM checks Content-Digest presence **before** checking the signature on POST/PUT endpoints. A request with a body but no Content-Digest (and no signature) returns 400, not 401. + +### WFM signature verification flow + +``` +1. Receive request +2. Check for Signature-Input + Signature headers + → Missing? → 400 "missing signature headers" +3. Check @authority is a covered component + → Missing? → reject +4. Reconstruct signature base string from covered components +5. Look up key using keyid from registered certs + → Not found? → reject +6. Verify ECDSA signature (IEEE P1363 format) + → len check: must be keySize×2 (64 bytes for P-256) + → Bad sig? → reject +7. (If body) verify Content-Digest matches actual body hash +8. Process request +``` + +--- + +## 8. Real WFM Behavior vs Spec (Important Differences) + +These are behaviors observed on the real Symphony WFM that differ from the OpenAPI spec. Always check here when tests fail unexpectedly. + +### Error field name: `Error` not `error` + +Every real WFM error response uses `"Error"` (capital E). The spec examples show `"error"` (lowercase): + +```json +// Spec examples show: { "error": "Invalid certificate" } +// Real WFM always returns: { "Error": "Invalid certificate" } +``` + +This affects every validation that checks error response fields. Always validate the `Error` field (capital E). + +### Unsigned POST/PUT returns 400, not 401 + +The spec indicates 401 for auth failures. The real WFM returns: +- **400** `{"Error": "missing signature headers"}` — for POST/PUT with missing signature +- **401** — for GET endpoints (bundles, deployment manifests) with missing signature + +Why? The WFM validates Content-Digest presence before checking the signature for body requests. A POST with neither Content-Digest nor Signature hits the Content-Digest validation first → 400. + +### Wrong Accept header returns 500, not 406 + +``` +GET /deployments with Accept: application/json + +Spec says: 406 Not Acceptable +Real WFM: 500 Internal Server Error + {"Error": "accept header not supported"} +``` + +### WFM does not validate capability content fields + +The spec implies `roles`, `interfaces`, and CPU `architecture` should only accept defined enum values. The real WFM accepts anything: + +| Field | Invalid Example | WFM Response | +|-------|----------------|--------------| +| `roles` | `["Unknown Role"]` | 201 Created | +| `interfaces[].type` | `"serial"` | 201 Created | +| `cpu.architecture` | `"sparc"` | 201 Created | + +This is a compliance gap in the current WFM. Tests document this behavior explicitly. + +### Onboarding: any cert is accepted (no 403) + +The spec defines a 403 "Client rejected" response for untrusted certificates. The real WFM accepts **any** cert — there is no trust-store validation at the onboarding endpoint. + +### Capabilities: apiVersion IS validated + +Despite not validating field content, the WFM does validate `apiVersion` on capabilities: +- Missing `apiVersion` → 400 (WFM validates this strictly) +- Wrong `apiVersion` format → 400 + +### Duplicate cert registration → 409 + +Sending the same certificate twice to `/onboarding`: +```json +{ "Error": "Device signature already exists" } ← HTTP 409 +``` + +### Bundle/manifest endpoints require pre-configured deployments + +`GET /bundles/{digest}` and `GET /deployments/{deploymentId}/{digest}` only return 200 when the WFM has actual deployments configured for that device. With no deployments: +- Bundle download with extracted digest (which is `null`) → 404 +- Deployment manifest with empty `deploymentId` → 301 redirect + +Steps 3.3–3.7 in the diamond group are excluded from the default run for this reason. Add them back to `group.json` testCases when deployments are configured in Symphony. + +--- + +## 9. The Node.js Scenario Runner — How It Works + +**File:** `conformance/wfm-supplier/run_wfm_scenarios.js` + +This runner is used when the group contains scenario files in the custom JSON format (detected by `discover_group_scenario_files`). It handles RFC 9421 request signing — which Postman/Newman cannot do natively. + +### Invocation + +```bash +node run_wfm_scenarios.js \ + # e.g. https://symphony.machine:8082/v1alpha2/margo + # filtered scenario list (temp file, built by run-tests.sh) + # output HTML report path + # directory containing device.key + device-cert.pem + ca-cert.pem + [group-name] # optional: displayed in report header + [group-version] # optional: displayed in report header +``` + +### Execution flow + +``` +1. Print banner (group name, WFM URL) + +For each scenario: + 2. Regenerate fresh ECDSA P-256 cert (new OpenSSL keygen per scenario) + 3. Reset context = {} + + For each step: + 4. Substitute {variables} in endpoint/headers/request_body using context + 5. Inject device cert PEM (base64) into onboarding bodies + 6. Compute Content-Digest (sha-256=:BASE64:) for body requests + 7. Sign request with RFC 9421 (unless skip_signing: true) + 8. Send HTTPS request + 9. Parse response JSON + 10. Check expected_status vs actual + 11. Run all validations + 12. If all pass: extract context values for later steps + 13. Print step result + + 14. Print scenario summary + +15. Write HTML report (group summary + step details) +16. Print final summary table (per-scenario pass/fail counts) +17. Exit 1 if any failures +``` + +### Variable substitution + +Steps extract values from responses into a shared `context` object and reference them in later steps using `{variableName}`: + +```json +// Setup step — extract clientId +"extract_context": { "clientId": "clientId" } + +// Later step — use it +"endpoint": "/api/v1/clients/{clientId}/capabilities", +"request_body": { "properties": { "id": "{clientId}" } } +``` + +Context is **reset between scenarios**. All steps in a scenario share the same context. + +### Certificate injection + +`"certificate": "./certs/device-cert.pem"` is a magic marker in scenario bodies. The runner replaces it with the actual base64-encoded PEM content of the current cert file. + +To send a literal string (for negative tests), set `"skip_certificate_injection": true` on the step. + +### Header case-insensitivity + +Node.js HTTP responses store all header names in lowercase (`etag`, not `ETag`). The runner's `getField()` function does case-insensitive lookup when traversing `_headers.*` paths, so you can write `"_headers.ETag"` in validations and it will correctly find `etag`. + +--- + +## 10. Test Scenario JSON Format (Custom Adapter Format) + +**File:** `Data-Generator/wfm-supplier/groups//test-scenarios.json` + +This format was created as an adapter to enable RFC 9421 signing in scenarios. See [Section 15](#15-design-notes--postman-vs-custom-format) for the full context on why this format exists alongside Postman. + +### File structure + +The file must be a JSON **array** of scenario objects. The runner detects this format (vs Postman) by checking `type == "array" and any .[]? has .steps array`. + +```json +[ + { + "id": "scenario-onboarding", + "name": "Device Onboarding", + "description": "Human-readable description of what this scenario tests.", + "steps": [ + { + "id": "step-1.1", + "name": "Get Root CA Certificate", + "method": "GET", + "endpoint": "/api/v1/onboarding/certificate", + "headers": {}, + "expected_status": 200, + "validations": [ + { "field": "certificate", "operation": "is_string" } + ], + "extract_context": {} + }, + { + "id": "step-1.2", + "name": "Onboard Trusted Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { "field": "clientId", "operation": "is_string" } + ], + "extract_context": { + "clientId": "clientId" + } + } + ] + } +] +``` + +### Step flags + +| Flag | Effect | +|------|--------| +| `skip_signing: true` | Send without `Signature`/`Signature-Input` headers. Content-Digest still computed and sent. Tests auth-failure paths. | +| `skip_certificate_injection: true` | Preserve the literal `certificate` value as-is instead of injecting the real base64 PEM. | + +### Validation operations + +| Operation | What it checks | +|-----------|---------------| +| `exists` | Field is present and not null | +| `is_string` | Field is a string | +| `is_number` | Field is a number | +| `is_array` | Field is an array | +| `not_empty` | Field exists and is not empty string | +| `equals` | Field exactly equals `value` (with variable substitution) | +| `contains` | String representation contains `value` | + +### Field path syntax + +| Path | Accesses | +|------|---------| +| `clientId` | Top-level response JSON field | +| `deployments.0.deploymentId` | Array element (numeric index) | +| `_headers.ETag` | Response header (case-insensitive) | +| `_body` | Raw response body string | +| `Error` | Top-level error field (capital E — WFM always uses this) | + +--- + +## 11. Group System — How Groups Work + +Groups are the core organizational unit of the conformance system. A Margo user organizes their test scenarios into groups, each group targeting a specific conformance level or area. + +### How a group is created (conformance.sh) + +1. User runs `conformance.sh` and selects "Create group" +2. The CLI prompts for: + - Group name (e.g., `diamond`, `silver`) + - Which scenario files to include in the group + - Which specific test IDs (scenario IDs or step IDs) from those files to include +3. `group.json` is generated with the selected `testCases` list +4. Multiple scenario files can be in one group directory — the runner merges them + +### group.json structure + +```json +{ + "name": "diamond", + "version": "1.2.1", + "persona": "wfm-supplier", + "description": "Full conformance test suite for WFM", + "testCases": [ + "scenario-onboarding", + "step-1.1", + "step-1.2", + "step-2.0", + "step-2.1" + ] +} +``` + +`testCases` can contain: +- **Scenario IDs** (e.g., `"scenario-onboarding"`) — includes the whole scenario +- **Step IDs** (e.g., `"step-1.1"`) — includes only that specific step (even if the rest of the scenario is not listed) +- **Legacy device IDs** — used by the Device Supplier persona + +### Step-level filtering in the runner + +When `run-tests.sh` builds the scenario file, `jq` applies two-level filtering: + +1. **Scenario selection**: Include a scenario if its ID or any of its step IDs appears in `testCases` +2. **Step filtering**: Within selected scenarios, keep only steps whose IDs are in `testCases` + +This means you can include a partial scenario — for example, include `step-3.0`, `step-3.1`, `step-3.2` from `scenario-deployments` without `step-3.3` through `step-3.7` (which need actual WFM deployments configured). + +### Multiple scenario files + +A group directory can contain multiple `test-scenarios.json` files (one per feature area, for example). The runner automatically discovers all files matching the format and merges them before filtering by `testCases`. + +``` +groups/diamond/ +├── group.json +├── onboarding-scenarios.json +├── capabilities-scenarios.json +└── deployment-scenarios.json +``` + +All three files are merged and then filtered by `group.json` → `testCases`. + +### Run reports are group-based + +The HTML report name includes the group name and timestamp: +``` +Runner/wfm-supplier/wfm-scenario-report-diamond_20260617_141857.html +``` + +The HTML report shows: +- Group metadata (name, version, WFM URL, run timestamp) +- Per-scenario summary table (steps / passed / failed) +- Full step-by-step details table + +--- + +## 12. Common Errors and How to Fix Them + +### All POST/PUT requests return 400 (ECDSA format bug) + +**Symptom:** Every signed body request fails with 400, no useful error message. + +**Root cause:** Node.js `createSign().sign()` produces DER/ASN.1 format (~70 bytes). The Go verifier checks `len(sig) == 64` for P-256 and immediately rejects. + +**Fix:** Use `dsaEncoding: 'ieee-p1363'` in `crypto.sign()`: +```javascript +crypto.sign('sha256', data, { key: privateKey, dsaEncoding: 'ieee-p1363' }) +``` + +**Diagnosis:** Log `signatureBytes.length` — must be exactly 64 for P-256. + +--- + +### `expected HTTP 201, got 400` on capabilities + +Most common causes in order: +1. `properties.id` ≠ `clientId` → Use `"id": "{clientId}"` in scenario JSON +2. Missing or wrong `apiVersion` → Must be `"device.margo.org/v1alpha1"` +3. Missing `kind` → Must be `"DeviceCapabilitiesManifest"` +4. Signature verification failure → Check ECDSA format (above) + +--- + +### `field "Error" is missing` in validation + +The WFM returns `"Error"` (capital E). All scenario validations must use `"field": "Error"` not `"field": "error"`. + +--- + +### `expected HTTP 201, got 409` on onboarding + +Certificate already registered from a previous run. Restart Symphony to clear registrations: +```bash +# wfm.sh menu: 4 = stop, 3 = start +cp ~/symphony/api/certs/ca-cert.pem \ + ~/nitin/sandbox/conformance/wfm-supplier/newman-data/certs/ca-cert.pem +``` + +--- + +### `expected HTTP 400, got 401` or vice versa on unsigned requests + +Different endpoint types return different status for missing signatures: +- **POST/PUT** with missing signature → **400** `"missing signature headers"` +- **GET** bundle/manifest with missing signature → **401** + +Match the `expected_status` to the endpoint type. + +--- + +### `expected HTTP 406, got 500` on deployments + +The real WFM returns 500 (not 406) for unsupported `Accept` headers. Set `expected_status: 500` and validate `Error` contains `"accept header"`. + +--- + +### `expected HTTP 200, got 404` on bundle download + +`bundle.digest` extracted from the deployments response is `null` — the WFM has no deployments configured. Remove steps 3.3–3.7 from `group.json` testCases, or configure a deployment in Symphony first. + +--- + +### `{clientId}` substitutes to empty string in URLs + +A setup (onboarding) step failed before extracting `clientId` into context. Look for the FAIL line on the setup step and fix that first. Ensure the setup step's ID is in `testCases`. + +--- + +### Keyid mismatch (signature verification fails silently) + +Ensure the `keyid` is computed as `hex(SHA-256(PKIX-DER-public-key))`. Any other format (raw bytes, cert fingerprint, hardcoded string) will cause the WFM to fail key lookup and reject the signature without a clear error. + +--- + +## 13. Certificate Lifecycle + +### During conformance testing + +A fresh ECDSA P-256 cert is generated for **each scenario** (to avoid 409 from repeated onboarding): +```bash +openssl ecparam -name prime256v1 -genkey -noout -out device.key +openssl req -new -x509 -days 365 -key device.key -out device-cert.pem \ + -subj "/C=IN/ST=GGN/L=Sector48/O=Margo/OU=Conformance/CN=device-" +``` + +This self-signed cert is submitted to the WFM during the onboarding step. The WFM stores the cert's public key and associates it with the issued `clientId`. Subsequent requests are signed with the private key, and the WFM verifies using the stored public key. + +### WFM CA certificate + +The WFM serves its API over HTTPS using a cert signed by its own CA. The Node.js runner loads the CA cert (`ca-cert.pem`) to verify the WFM's TLS certificate. + +Get it from: `~/symphony/api/certs/ca-cert.pem` +Copy to: `conformance/wfm-supplier/newman-data/certs/ca-cert.pem` + +### Real device-agent certificate + +The real device-agent uses a static cert configured in `config/device-public.crt`. This is submitted once at onboarding and reused for all subsequent requests. The `clientId` received at onboarding is persisted by the agent. + +--- + +## 14. How the Real Device-Agent Works + +**Location:** `poc/device/agent/` +**Config:** `poc/device/agent/config/config.yaml` + +```yaml +wfm: + sbiUrl: https://symphony.machine:8082/v1alpha2/margo + clientPlugins: + requestSigner: + enabled: true + hashAlgo: "sha256" + signatureAlgo: "ecdsa" # or "rsa" + signatureFormat: "structured" + keyRef: + path: "./config/device-private.key" + tlsHelper: + enabled: true + caKeyRef: + path: "./config/ca-cert.pem" + +capabilities: + readFromFile: ./config/capabilities.json +``` + +### Capabilities file + +```json +{ + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-id-from-manufacturer", + "vendor": "Northstar Industrial Applications", + ... + } +} +``` + +**Important:** The agent **overwrites** `properties.id` at runtime with the `clientId` received from the WFM during onboarding. This is the same reason conformance scenarios use `"id": "{clientId}"` — both must match the WFM-issued clientId. + +### Agent startup sequence + +``` +1. Load private key, compute keyid (SHA-256 hex of PKIX DER public key) +2. GET /api/v1/onboarding/certificate → get WFM CA cert for TLS verification +3. POST /api/v1/onboarding with device cert → receive clientId +4. POST /api/v1/clients/{clientId}/capabilities + with properties.id = clientId (overrides capabilities.json value) +5. Poll GET /api/v1/clients/{clientId}/deployments every 15 seconds + → If ETag changed: process new/updated deployments +6. When deployments change: deploy/undeploy via Kubernetes/Docker runtime +7. After each deployment action: POST deployment status back to WFM +``` + +### Signing in Go (`shared-lib/crypto/signer.go`) + +Uses `lestrrat-go/htmsig` library: +- Body requests: `@method` + `@target-uri` + `@authority` + `content-digest` +- No-body requests: `@method` + `@target-uri` + `@authority` +- The `lestrrat-go/dsig` library produces IEEE P1363 ECDSA signatures (raw r||s) + +This is the reference implementation that the Node.js runner in `run_wfm_scenarios.js` must exactly match. + +--- + +## 15. Design Notes — Postman vs Custom Format + +This section explains a design tension that is important to understand when extending the conformance suite. + +### The intended design + +Margo users create their test scenarios in **Postman** (because Postman has a rich UI for designing API test cases) and export them as Postman collection JSON files. The conformance system runs these collections using **Newman** and generates reports. + +The `conformance.sh` CLI reads Postman collection files, presents the test items to the user, and lets them select which items to include in a group. The `group.json` records those selections. The `run-tests.sh` Newman path executes the filtered collection. + +### The signing problem + +**Postman/Newman cannot natively implement RFC 9421 HTTP Message Signatures.** RFC 9421 requires: +- Computing a structured signature base string from specific HTTP components +- ECDSA signing with IEEE P1363 encoding (not DER) +- Setting `Signature-Input` and `Signature` headers before the request is sent + +Postman pre-request scripts can run JavaScript, but they cannot call Node.js `crypto` APIs in the way needed, and they cannot reliably produce the correct IEEE P1363 ECDSA signature format. + +### The custom format solution + +The `run_wfm_scenarios.js` runner and the custom `test-scenarios.json` format were created to solve this. The format is: +- A JSON array of scenario objects (not Postman format) +- Each step specifies method, endpoint, body, headers, expected status, and validations +- The runner handles all signing, cert injection, and context propagation internally + +### Coexistence in the current system + +`run-tests.sh` uses both: + +```bash +# Detected by: type == "array" and any .[]? has .steps array +if custom-format scenario files exist: + use run_wfm_scenarios.js (RFC 9421 signing) +else: + discover Postman collection files + use Newman (no signing) +``` + +The detection happens in `discover_group_scenario_files()`. The Postman/Newman path is still available for test scenarios that don't need RFC 9421 signing (e.g., testing endpoints that don't require signatures). + +### What this means for you + +- If you are adding new WFM Supplier tests that require RFC 9421 signing → use the custom JSON format in `test-scenarios.json` +- If you are bringing a Postman collection that uses pre-request scripts for signing → the Newman path will run it, but signing correctness depends on your Postman scripts +- Future work: a converter from Postman collection format to the custom JSON format would allow users to author in Postman and run via the Node.js signed runner + +--- + +## 16. Adding or Modifying Tests + +### Add a step to an existing scenario + +1. Open `Data-Generator/wfm-supplier/groups//test-scenarios.json` +2. Find the target scenario and add a new step object with a unique ID (e.g., `step-5.8`) +3. Add that step ID to `group.json` → `testCases` +4. Run tests to verify + +### Add a new scenario + +1. Add a new object to the top-level array in `test-scenarios.json` with `"id"`, `"name"`, `"description"`, `"steps"` +2. Give steps unique IDs (e.g., `step-8.0`, `step-8.1`) +3. Add step IDs to `group.json` → `testCases` + +### Temporarily narrow the test run + +Edit `group.json` to include only the step IDs you want to test: +```json +{ "testCases": ["step-5.1", "step-5.2"] } +``` + +Run tests, then restore the full list. + +### Enable deployment-dependent steps (3.3–3.7) + +These steps test bundle download, deployment manifest download, and status reporting. They require a deployment configured in Symphony: + +1. Configure a deployment in Symphony for the test device +2. Add `"step-3.3"`, `"step-3.4"`, `"step-3.5"`, `"step-3.6"`, `"step-3.7"` to `group.json` → `testCases` + +### Updating a step when WFM behavior changes + +1. Find the step by ID in `test-scenarios.json` +2. Update `expected_status` to match the actual WFM response +3. Update `validations` fields/values to match actual response JSON +4. Always check `"field": "Error"` (capital E) — WFM always uses this + +--- + +## Quick Reference Card + +| Item | Value / Rule | +|------|-------------| +| **WFM base URL** | `https://symphony.machine:8082/v1alpha2/margo` | +| **API path prefix** | `/api/v1/` (all endpoints) | +| **Margo spec** | [workload-management-api-1.0.0.yaml](https://raw.githubusercontent.com/margo/specification/pre-draft/system-design/specification/margo-management-interface/workload-management-api-1.0.0.yaml) | +| **Error field name** | `"Error"` — capital E, always | +| **Capabilities success** | `{"message": "Device capabilities reported successfully"}` | +| **`properties.id` rule** | MUST equal `clientId` from onboarding response | +| **Signature components (GET)** | `@method`, `@target-uri`, `@authority` | +| **Signature components (POST/PUT)** | `@method`, `@target-uri`, `@authority`, `content-digest` | +| **ECDSA format** | IEEE P1363 (raw r\|\|s, **64 bytes** for P-256) — NOT DER | +| **Content-Digest format** | `sha-256=:BASE64:` (colons around base64) | +| **keyid formula** | `hex(SHA-256(PKIX-DER-public-key))` | +| **Cert type** | ECDSA P-256 (`prime256v1`), self-signed | +| **Cert regeneration** | Per scenario (avoids 409 on re-onboarding) | +| **Unsigned POST/PUT** | 400 "missing signature headers" | +| **Unsigned GET bundle/manifest** | 401 | +| **Wrong Accept on /deployments** | 500 (spec says 406) | +| **Duplicate cert** | 409 "Device signature already exists" | +| **CA cert path (runtime)** | `wfm-supplier/newman-data/certs/ca-cert.pem` | +| **CA cert source** | `~/symphony/api/certs/ca-cert.pem` | +| **Deployment steps (3.3–3.7)** | Excluded by default — need WFM deployments configured | +| **Scenario format detection** | `type == "array" and any .[]? has .steps array` | diff --git a/Application-Supplier-Service/application.go b/Application-Supplier-Service/application.go new file mode 100644 index 0000000..44306df --- /dev/null +++ b/Application-Supplier-Service/application.go @@ -0,0 +1,760 @@ +package main + +import ( + "fmt" + "regexp" +) + +func ValidateAppDescription( + app *ApplicationDescription, + report *ValidationReport, +) error { + + validateTopLevel( + app, + report, + ) + + validateMetadata( + app, + report, + ) + + componentNames, _ := + validateDeploymentProfiles( + app, + report, + ) + + schemas, _ := + validateSchemas( + app, + report, + ) + + validateConfiguration( + app, + report, + schemas, + ) + + validateParameterTargets( + app, + report, + componentNames, + ) + + return nil +} + + +func validateTopLevel( + app *ApplicationDescription, + report *ValidationReport, +) error { + + check( + report, + "apiVersion", + "string", + "Required (non-empty)", + ) + + if app.APIVersion == "" { + + fail( + report, + "(missing)", + "API version is required but was not provided.", + ) + + } else { + + pass( + report, + app.APIVersion, + "API version conforms to the required specification.", + ) + } + + check( + report, + "kind", + "string", + "ApplicationDescription", + ) + + if app.Kind == "" { + + fail( + report, + "(missing)", + "Application type is required but was not provided.", + ) + + } else if app.Kind != "ApplicationDescription" { + + fail( + report, + app.Kind, + "Application type does not conform to the required baseline. Expected 'ApplicationDescription'.", + ) + + } else { + + pass( + report, + app.Kind, + "Application type conforms to the required baseline.", + ) + } + + check( + report, + "id", + "string", + "lowercase letters, numbers and dashes only, max length=200", + ) + + re := regexp.MustCompile( + `^[a-z0-9-]{1,200}$`, + ) + + if app.ID == "" { + + fail( + report, + "(missing)", + "Application identifier is required but was not provided.", + ) + + } else if !re.MatchString(app.ID) { + + fail( + report, + app.ID, + "Application identifier does not conform to the required naming convention.", + ) + + } else { + + pass( + report, + app.ID, + "Application identifier conforms to the required naming convention.", + ) + } + + return nil +} + +func validateDeploymentProfiles( + app *ApplicationDescription, + report *ValidationReport, +) (map[string]bool, error) { + + check( + report, + "deploymentProfile", + "array", + "At least one deployment profile", + ) + + if len(app.DeploymentProfile) == 0 { + + fail( + report, + "0 deployment profile(s)", + "At least one deployment profile is required.", + ) + + } else { + + pass( + report, + fmt.Sprintf( + "%d deployment profile(s)", + len(app.DeploymentProfile), + ), + "Deployment profile configuration conforms to the required baseline.", + ) + } + + componentNames := make(map[string]bool) + + for _, profile := range app.DeploymentProfile { + + check( + report, + "deploymentProfile.type", + "string", + "helm | compose", + ) + + if profile.Type == "" { + + fail( + report, + "(missing)", + "Deployment profile type is required but was not provided.", + ) + + } else if profile.Type != "helm" && + profile.Type != "compose" { + + fail( + report, + profile.Type, + "Deployment profile type does not conform to the supported deployment specifications.", + ) + + } else { + + pass( + report, + profile.Type, + "Deployment profile type conforms to the supported deployment specifications.", + ) + } + + check( + report, + "deploymentProfile.id", + "string", + "Required (non-empty)", + ) + + if profile.ID == "" { + + fail( + report, + "(missing)", + "Deployment profile identifier is required but was not provided.", + ) + + } else { + + pass( + report, + profile.ID, + "Deployment profile configuration conforms to the defined specification.", + ) + } + + if len(profile.Components) == 0 { + + fail( + report, + "0 component(s)", + "Deployment profile does not contain any component definitions.", + ) + } + + for _, component := range profile.Components { + + check( + report, + "component.name", + "string", + "Required (non-empty)", + ) + + if component.Name == "" { + + fail( + report, + "(missing)", + "Component name is required but was not provided.", + ) + + } else { + + componentNames[component.Name] = true + + pass( + report, + component.Name, + "Component configuration conforms to the defined specification.", + ) + } + + if len(component.Properties) == 0 { + + fail( + report, + "0 properties", + "Component configuration properties are not defined.", + ) + } + + if profile.Type == "helm" { + + check( + report, + "repository", + "string", + "Repository URL required", + ) + + repository, ok := + component.Properties["repository"] + + if !ok { + + fail( + report, + "(missing)", + "Repository configuration is required but was not provided.", + ) + + } else { + + pass( + report, + fmt.Sprintf("%v", repository), + "Repository configuration conforms to the deployment requirements.", + ) + } + + check( + report, + "revision", + "string", + "Required (non-empty)", + ) + + revision, ok := + component.Properties["revision"] + + if !ok { + + fail( + report, + "(missing)", + "Revision information is required but was not provided.", + ) + + } else { + + pass( + report, + fmt.Sprintf("%v", revision), + "Revision information conforms to the deployment requirements.", + ) + } + } + + if profile.Type == "compose" { + + check( + report, + "compose.packageLocation", + "string", + "Required package location", + ) + + packageLocation, ok := + component.Properties["packageLocation"] + + if !ok { + + fail( + report, + "(missing)", + "Package location is required but was not provided.", + ) + + } else { + + pass( + report, + fmt.Sprintf("%v", packageLocation), + "Package location conforms to the deployment requirements.", + ) + } + } + } + } + + return componentNames, nil +} + + +func validateSchemas( + app *ApplicationDescription, + report *ValidationReport, +) (map[string]bool, error) { + + schemas := make(map[string]bool) + + for _, schema := range app.Configuration.Schema { + + check( + report, + "schema", + "string", + "name and dataType required", + ) + + if schema.Name == "" { + + fail( + report, + "(missing)", + "Schema name is required but was not provided.", + ) + + } else if schema.DataType == "" { + + fail( + report, + "(missing)", + fmt.Sprintf( + "Schema '%s' does not define a data type.", + schema.Name, + ), + ) + + } else { + + schemas[schema.Name] = true + + pass( + report, + schema.Name, + fmt.Sprintf( + "Schema '%s' conforms to the defined specification. Data type='%s', AllowEmpty=%t.", + schema.Name, + schema.DataType, + schema.AllowEmpty, + ), + ) + } + } + + return schemas, nil +} + + +func validateConfiguration( + app *ApplicationDescription, + report *ValidationReport, + schemas map[string]bool, +) error { + + for _, section := range app.Configuration.Sections { + + check( + report, + "configuration.section", + "string", + "Required (non-empty)", + ) + + pass( + report, + section.Name, + "Configuration section has been successfully identified.", + ) + + for _, setting := range section.Settings { + + check( + report, + fmt.Sprintf( + "setting.parameter.%s", + setting.Parameter, + ), + "reference", + "Must match a parameter definition", + ) + + if _, ok := + app.Parameters[setting.Parameter]; !ok { + + fail( + report, + setting.Parameter, + fmt.Sprintf( + "Referenced parameter '%s' is not defined.", + setting.Parameter, + ), + ) + + } else { + + pass( + report, + setting.Parameter, + fmt.Sprintf( + "Parameter '%s' conforms to the defined specification.", + setting.Parameter, + ), + ) + } + + if setting.Schema != "" { + + check( + report, + fmt.Sprintf( + "setting.parameter.%s.schema", + setting.Parameter, + ), + "reference", + "Must match a schema definition", + ) + + if !schemas[setting.Schema] { + + fail( + report, + setting.Schema, + fmt.Sprintf( + "Referenced schema '%s' is not defined.", + setting.Schema, + ), + ) + + } else { + + pass( + report, + setting.Schema, + fmt.Sprintf( + "Schema '%s' conforms to the defined specification.", + setting.Schema, + ), + ) + } + } + } + } + + return nil +} + +func validateParameterTargets( + app *ApplicationDescription, + report *ValidationReport, + componentNames map[string]bool, +) error { + + for parameterName, parameter := + range app.Parameters { + + for _, target := + range parameter.Targets { + + for _, component := + range target.Components { + + check( + report, + fmt.Sprintf( + "parameter.%s", + parameterName, + ), + "reference", + "Must match a deployment component", + ) + + if !componentNames[component] { + + fail( + report, + component, + fmt.Sprintf( + "Parameter '%s' references a component that does not conform to the defined deployment configuration.", + parameterName, + ), + ) + + } else { + + pass( + report, + component, + fmt.Sprintf( + "Parameter '%s' conforms to the defined component mapping requirements. Pointer='%s'.", + parameterName, + target.Pointer, + ), + ) + } + } + } + } + + return nil +} + +func validateMetadata( + app *ApplicationDescription, + report *ValidationReport, +) error { + + check( + report, + "metadata.name", + "string", + "Required (non-empty)", + ) + + if app.Metadata.Name == "" { + + fail( + report, + "(missing)", + "Application name is required but was not provided.", + ) + + } else { + + pass( + report, + app.Metadata.Name, + "Application name conforms to the required specification.", + ) + } + + check( + report, + "metadata.version", + "string", + "Required (non-empty)", + ) + + if app.Metadata.Version == "" { + + fail( + report, + "(missing)", + "Application version is required but was not provided.", + ) + + } else { + + pass( + report, + app.Metadata.Version, + "Application version conforms to the required specification.", + ) + } + + check( + report, + "metadata.catalog.organization", + "array", + "At least one organization", + ) + + if len(app.Metadata.Catalog.Organization) == 0 { + + fail( + report, + "0 organization(s)", + "At least one organization definition is required.", + ) + + } else { + + pass( + report, + fmt.Sprintf( + "%d organization(s)", + len(app.Metadata.Catalog.Organization), + ), + "Organization information conforms to the required specification.", + ) + } + + for _, org := range app.Metadata.Catalog.Organization { + + check( + report, + "metadata.catalog.organization.name", + "string", + "Required (non-empty)", + ) + + if org.Name == "" { + + fail( + report, + "(missing)", + "Organization name is required but was not provided.", + ) + + } else { + + pass( + report, + org.Name, + "Organization information conforms to the required specification.", + ) + } + } + + return nil +} + +// func check(report *ValidationReport, msg string) { +// fmt.Println("Validate", msg) +// report.Check(msg) +// } + +// func pass(report *ValidationReport, msg string) { +// fmt.Println("PASS", msg) +// report.Pass(msg) +// } + +// func fail(report *ValidationReport, msg string) error { +// fmt.Println("FAIL", msg) +// report.Fail(msg) +// return fmt.Errorf(msg) +// } + +func check( + report *ValidationReport, + field string, + dataType string, + expected string, +) { + + fmt.Println("Validate", field) + + report.Check( + field, + dataType, + expected, + ) +} + +func pass( + report *ValidationReport, + actual string, + details string, +) { + + fmt.Println("PASS", details) + + report.Pass( + actual, + details, + ) +} + +func fail( + report *ValidationReport, + actual string, + details string, +) { + + fmt.Println("FAIL", details) + + report.Fail( + actual, + details, + ) +} diff --git a/Application-Supplier-Service/compose.go b/Application-Supplier-Service/compose.go new file mode 100644 index 0000000..72f5012 --- /dev/null +++ b/Application-Supplier-Service/compose.go @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "net/http" + "os/exec" + "strings" +) + +func CheckHTTPS(url string) error { + + resp, err := http.Head(url) + + if err != nil { + return err + } + + if resp.StatusCode >= 400 { + return fmt.Errorf( + "url not reachable: %d", + resp.StatusCode, + ) + } + + return nil +} + +func CheckOCI(location string) error { + + cmd := exec.Command( + "oras", + "manifest", + "fetch", + location, + ) + + out, err := cmd.CombinedOutput() + + if err != nil { + + return fmt.Errorf( + "oci unreachable: %s", + string(out), + ) + } + + return nil +} + +func CheckPackageLocation( + location string, +) error { + + if strings.HasPrefix( + location, + "https://", + ) { + + return CheckHTTPS(location) + } + + if strings.HasPrefix( + location, + "http://", + ) { + + return CheckHTTPS(location) + } + + if strings.HasPrefix( + location, + "oci://", + ) { + + return CheckOCI(location) + } + + return fmt.Errorf( + "unsupported packageLocation: %s", + location, + ) +} \ No newline at end of file diff --git a/Application-Supplier-Service/extractor.go b/Application-Supplier-Service/extractor.go new file mode 100644 index 0000000..2b6ed33 --- /dev/null +++ b/Application-Supplier-Service/extractor.go @@ -0,0 +1,88 @@ +package main + +import ( + "archive/tar" + "archive/zip" + "compress/gzip" + "io" + "os" + "path/filepath" +) + +func ExtractZip(src, dest string) error { + + r, err := zip.OpenReader(src) + if err != nil { + return err + } + defer r.Close() + + for _, f := range r.File { + + path := filepath.Join(dest, f.Name) + + if f.FileInfo().IsDir() { + os.MkdirAll(path, 0755) + continue + } + + os.MkdirAll(filepath.Dir(path), 0755) + + rc, _ := f.Open() + + out, _ := os.Create(path) + + io.Copy(out, rc) + + out.Close() + rc.Close() + } + + return nil +} + +func ExtractTarGz(src, dest string) error { + + file, err := os.Open(src) + if err != nil { + return err + } + + gzr, err := gzip.NewReader(file) + if err != nil { + return err + } + + tr := tar.NewReader(gzr) + + for { + header, err := tr.Next() + + if err == io.EOF { + break + } + + if err != nil { + return err + } + + target := filepath.Join(dest, header.Name) + + switch header.Typeflag { + + case tar.TypeDir: + os.MkdirAll(target, 0755) + + case tar.TypeReg: + os.MkdirAll(filepath.Dir(target), 0755) + + f, _ := os.Create(target) + + io.Copy(f, tr) + + f.Close() + } + } + + return nil +} diff --git a/Application-Supplier-Service/helm.go b/Application-Supplier-Service/helm.go new file mode 100644 index 0000000..605f1dd --- /dev/null +++ b/Application-Supplier-Service/helm.go @@ -0,0 +1,48 @@ +package main + +import ( + "fmt" + "strings" +) + +func ValidateHelmComponent( + c Component, +) error { + + repo, ok := + c.Properties["repository"] + + if !ok { + + return fmt.Errorf( + "repository missing", + ) + } + + repository := + repo.(string) + + if strings.HasPrefix( + repository, + "https://", + ) || strings.HasPrefix( + repository, + "http://", + ) { + + return CheckHTTPS(repository) + } + + if strings.HasPrefix( + repository, + "oci://", + ) { + + return CheckOCI(repository) + } + + return fmt.Errorf( + "unsupported repository: %s", + repository, + ) +} \ No newline at end of file diff --git a/Application-Supplier-Service/main.go b/Application-Supplier-Service/main.go new file mode 100644 index 0000000..186b703 --- /dev/null +++ b/Application-Supplier-Service/main.go @@ -0,0 +1,394 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "time" + "gopkg.in/yaml.v3" +) + +func main() { + + if len(os.Args) < 2 { + + fmt.Println( + "Usage: validator ", + ) + + os.Exit(1) + } + + inputPath := os.Args[1] + + var workDir string + + info, err := os.Stat(inputPath) + + if err != nil { + panic(err) + } + + //-------------------------------------------------- + // Folder + //-------------------------------------------------- + + if info.IsDir() { + + workDir = inputPath + + } else if filepath.Ext(inputPath) == ".zip" { + + workDir = "./workdir" + + os.RemoveAll(workDir) + + err = ExtractZip( + inputPath, + workDir, + ) + + if err != nil { + panic(err) + } + + } else if filepath.Ext(inputPath) == ".gz" { + + workDir = "./workdir" + + os.RemoveAll(workDir) + + err = ExtractTarGz( + inputPath, + workDir, + ) + + if err != nil { + panic(err) + } + + } else { + + fmt.Println( + "Unsupported input type", + ) + + os.Exit(1) + } + + fmt.Println( + "Extracted Path:", + workDir, + ) + + //-------------------------------------------------- + // Find Application Description + //-------------------------------------------------- + + appYaml, err := + FindApplicationDescription( + workDir, + ) + + if err != nil { + panic(err) + } + + fmt.Println( + "Application Description:", + appYaml, + ) + + //-------------------------------------------------- + // Read YAML + //-------------------------------------------------- + + data, err := + os.ReadFile(appYaml) + + if err != nil { + panic(err) + } + + //-------------------------------------------------- + // Handle Template Variables + //-------------------------------------------------- + // + // Example: + // + // repository: {{HELM_REPOSITORY}} + // revision: {{CHART_VERSION}} + // + //-------------------------------------------------- + + content := string(data) + + placeholderRegex := + regexp.MustCompile(`\{\{[^}]+\}\}`) + + content = + placeholderRegex.ReplaceAllStringFunc( + content, + func(s string) string { + + return "\"" + s + "\"" + }, + ) + + data = []byte(content) + + //-------------------------------------------------- + // Parse YAML + //-------------------------------------------------- + + var app ApplicationDescription + + err = yaml.Unmarshal( + data, + &app, + ) + + appName := app.Metadata.Name + +if appName == "" { + appName = filepath.Base(workDir) +} + +reportDir := filepath.Join( + "..", + "Runner", + "application-supplier", +) + +_ = os.MkdirAll( + reportDir, + os.ModePerm, +) + +reportFile := filepath.Join( + reportDir, + fmt.Sprintf( + "%s_%s.html", + appName, + time.Now().Format("02-01-2006_15-04-05"), + ), +) + + if err != nil { + + fmt.Println( + "\nYAML PARSE FAILED", + ) + + fmt.Println( + "File:", + appYaml, + ) + + fmt.Println( + "Error:", + err, + ) + + os.Exit(1) + } +//-------------------------------------------------- +// Application Validation +//-------------------------------------------------- + +report := NewValidationReport() + +report.ApplicationName = app.Metadata.Name +report.ApplicationVersion = app.Metadata.Version + +if report.ApplicationName == "" { + report.ApplicationName = app.ID +} + +err = ValidateAppDescription( + &app, + report, +) + +if err != nil { + + report.Status = "FAILED" + +_ = report.GenerateHTMLReport( + reportFile, +) + + fmt.Println( + "\nVALIDATION FAILED:", + ) + + fmt.Println(err) + + os.Exit(1) +} + +fmt.Println( + "\nApplication Description Validation PASSED", +) + + //-------------------------------------------------- + // Deployment Profile Validation + //-------------------------------------------------- + + for _, profile := + range app.DeploymentProfile { + + fmt.Println( + "\nDeployment Type:", + profile.Type, + ) + + switch profile.Type { + + //-------------------------------------------------- + // HELM + //-------------------------------------------------- + + case "helm": + + for _, component := + range profile.Components { + +report.Check( + fmt.Sprintf( + "Validating Helm component '%s'", + component.Name, + ), + "network", + "Helm repository reachable", +) + + err := ValidateHelmComponent( + component, +) + +if err != nil { + +report.Fail( + "unreachable", + fmt.Sprintf( + "Helm validation failed for component '%s' : %v", + component.Name, + err, + ), +) + + fmt.Println( + "FAIL:", + err, + ) + + continue +} + +report.Pass( + "reachable", + fmt.Sprintf( + "Helm repository reachable for component '%s'", + component.Name, + ), +) + +fmt.Println( + "PASS: Helm Repository Reachable", +) + } + + //-------------------------------------------------- + // COMPOSE + //-------------------------------------------------- + + case "compose": + + for _, component := + range profile.Components { + + location := + component.Properties["packageLocation"].(string) + + report.Check( + "compose.packageLocation", + "network", + "Package location reachable", +) + + err := CheckPackageLocation( + location, +) + +if err != nil { + + report.Fail( + "unreachable", + fmt.Sprintf( + "packageLocation unreachable for component '%s' : %v", + component.Name, + err, + ), +) + + fmt.Println( + "FAIL:", + err, + ) + + continue +} + +report.Pass( + location, + fmt.Sprintf( + "packageLocation reachable for component '%s'", + component.Name, + ), +) + +fmt.Println( + "PASS: packageLocation reachable", +) + } + + default: + + fmt.Printf( + "Unsupported deployment type %s\n", + profile.Type, + ) + } + } + + fmt.Println( + "\nConformance Validation Completed", +) + +err = report.GenerateHTMLReport( + reportFile, +) + +reportPath, _ := filepath.Abs( + reportFile, +) + +fmt.Println() +fmt.Println("=====================================") +fmt.Println("Validation Report Generated") +fmt.Println("Report Path:", reportPath) +fmt.Println("Validation Result :", report.Status) + +fmt.Println("=====================================") +fmt.Println() + +if err != nil { + + fmt.Println( + "failed to generate report:", + err, + ) +} +} \ No newline at end of file diff --git a/Application-Supplier-Service/models.go b/Application-Supplier-Service/models.go new file mode 100644 index 0000000..02b629b --- /dev/null +++ b/Application-Supplier-Service/models.go @@ -0,0 +1,69 @@ +package main + +type ApplicationDescription struct { + APIVersion string `yaml:"apiVersion"` + Kind string `yaml:"kind"` + ID string `yaml:"id"` + Metadata Metadata `yaml:"metadata"` + DeploymentProfile []DeploymentProfile `yaml:"deploymentProfiles"` + Parameters map[string]Parameter `yaml:"parameters"` + Configuration Configuration `yaml:"configuration"` +} + +type Metadata struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Catalog Catalog `yaml:"catalog"` +} + +type Catalog struct { + Organization []Organization `yaml:"organization"` +} + +type Organization struct { + Name string `yaml:"name"` +} + +type DeploymentProfile struct { + Type string `yaml:"type"` + ID string `yaml:"id"` + Components []Component `yaml:"components"` +} + +type Component struct { + Name string `yaml:"name"` + Properties map[string]interface{} `yaml:"properties"` +} + +type Parameter struct { + Value interface{} `yaml:"value"` + Targets []Target `yaml:"targets"` +} + +type Target struct { + Pointer string `yaml:"pointer"` + Components []string `yaml:"components"` +} + +type Configuration struct { + Sections []Section `yaml:"sections"` + Schema []SchemaDef `yaml:"schema"` +} + +type Section struct { + Name string `yaml:"name"` + Settings []Setting `yaml:"settings"` +} + +type Setting struct { + Parameter string `yaml:"parameter"` + Name string `yaml:"name"` + Description string `yaml:"description"` + Schema string `yaml:"schema"` +} + +type SchemaDef struct { + Name string `yaml:"name"` + DataType string `yaml:"dataType"` + AllowEmpty bool `yaml:"allowEmpty"` +} \ No newline at end of file diff --git a/Application-Supplier-Service/report.go b/Application-Supplier-Service/report.go new file mode 100644 index 0000000..db92bea --- /dev/null +++ b/Application-Supplier-Service/report.go @@ -0,0 +1,418 @@ +package main + +import ( + "fmt" + "html/template" + "os" + "time" +) + +type ValidationEntry struct { + Field string + Status string + Type string + Rule string + ActualValue string + Remarks string +} + + +type ValidationReport struct { + Entries []ValidationEntry + Status string + ApplicationName string + ApplicationVersion string +} + +const reportTemplate = ` + + + + + +Application Supplier Conformance Test Report + + + + + + + +
+ +

+ Application Supplier Conformance Test Report +

+ +

+ Application: + {{.ApplicationName}} +

+ +

+ Application Version: + {{.ApplicationVersion}} +

+ +

+ Generated: + {{now}} +

+ +
+ +
+ +

Summary

+ +

+ Total Checks: {{len .Entries}} + | + + ✅ Passed: {{passedCount .Entries}} + + | + + ❌ Failed: {{failedCount .Entries}} + +

+ +

+ + Success Rate: {{successRate .Entries}}% + +

+ +
+ + + + + + + + + + + + +{{range .Entries}} + + + + + + + + + + + + + + +{{end}} + +
Application Description AttributeStatusTypeValidation Rule (Expected)Actual ValueRemarks
{{.Field}} + + {{if eq .Status "PASS"}} +
+
PASS
+ + {{else if eq .Status "FAIL"}} +
+
FAIL
+ + {{else}} + {{.Status}} + {{end}} + +
{{.Type}}{{.Rule}}{{.ActualValue}}{{.Remarks}}
+ + + +` + +func NewValidationReport() *ValidationReport { + return &ValidationReport{ + Status: "PASSED", + } +} + +func (r *ValidationReport) Log( + validate string, + details string, + status string, +) { + + r.Entries = append( + r.Entries, + ValidationEntry{ + Field: validate, + Remarks: details, + Status: status, +}, + ) + + if status == "FAIL" { + r.Status = "FAILED" + } +} + +func (r *ValidationReport) Check( + field string, + dataType string, + expected string, +) { + + r.Entries = append( + r.Entries, + ValidationEntry{ + Field: field, + Type: dataType, + Rule: expected, + }, + ) +} + + +func (r *ValidationReport) Pass( + actual string, + details string, +) { + + if len(r.Entries) == 0 { + return + } + + last := + &r.Entries[len(r.Entries)-1] + + last.Status = "PASS" + last.ActualValue = actual + last.Remarks = details +} + +func (r *ValidationReport) Fail( + actual string, + details string, +) { + + if len(r.Entries) == 0 { + return + } + + last := + &r.Entries[len(r.Entries)-1] + + last.Status = "FAIL" + last.ActualValue = actual + last.Remarks = details + + r.Status = "FAILED" +} + + + +func (r ValidationReport) GenerateHTMLReport( + file string, +) error { + + funcMap := template.FuncMap{ + + "lower": func(s string) string { + + switch s { + + case "PASS": + return "pass" + + case "FAIL": + return "fail" + + default: + return "validate" + } + }, + + "now": func() string { + + return time.Now(). + UTC(). + Format( + "2006-01-02T15:04:05Z", + ) + }, + + "passedCount": func( + entries []ValidationEntry, + ) int { + + count := 0 + + for _, e := range entries { + + if e.Status == "PASS" { + count++ + } + } + + return count + }, + + "failedCount": func( + entries []ValidationEntry, + ) int { + + count := 0 + + for _, e := range entries { + + if e.Status == "FAIL" { + count++ + } + } + + return count + }, + + "successRate": func( + entries []ValidationEntry, + ) string { + + total := 0 + passed := 0 + + for _, e := range entries { + + if e.Status == "PASS" || + e.Status == "FAIL" { + + total++ + + if e.Status == "PASS" { + passed++ + } + } + } + + if total == 0 { + return "0.0" + } + + return fmt.Sprintf( + "%.1f", + float64(passed)*100/float64(total), + ) + }, + } + + tmpl := template.Must( + template.New("report"). + Funcs(funcMap). + Parse(reportTemplate), + ) + + f, err := os.Create(file) + + if err != nil { + return err + } + + defer f.Close() + + return tmpl.Execute(f, r) +} \ No newline at end of file diff --git a/Application-Supplier-Service/utils.go b/Application-Supplier-Service/utils.go new file mode 100644 index 0000000..0ec5b72 --- /dev/null +++ b/Application-Supplier-Service/utils.go @@ -0,0 +1,81 @@ +package main + + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "gopkg.in/yaml.v3" +) + + +func FindApplicationDescription(root string) (string, error) { + + var found string + + err := filepath.Walk( + root, + func(path string, info os.FileInfo, err error) error { + + if err != nil || info == nil { + return nil + } + + if info.IsDir() { + return nil + } + + ext := strings.ToLower( + filepath.Ext(path), + ) + + if ext != ".yaml" && + ext != ".yml" { + + return nil + } + + data, err := os.ReadFile(path) + + if err != nil { + return nil + } + + var obj struct { + Kind string `yaml:"kind"` + } + + if err := yaml.Unmarshal( + data, + &obj, + ); err != nil { + + return nil + } + + if obj.Kind == + "ApplicationDescription" { + + found = path + } + + return nil + }, + ) + + if err != nil { + return "", err + } + + if found == "" { + + return "", + fmt.Errorf( + "ApplicationDescription not found", + ) + } + + return found, nil +} \ No newline at end of file diff --git a/Application-Supplier/margo-package/margo.yaml b/Application-Supplier/margo-package/margo.yaml new file mode 100644 index 0000000..eb35da1 --- /dev/null +++ b/Application-Supplier/margo-package/margo.yaml @@ -0,0 +1,61 @@ +apiVersions: margo.org/v1-alpha1 +kind: ApplicationDescription +id: com-northstartida-hello-world +metadata: + name: Hello World + description: A basic hello world application + version: "1.0" + catalog: + application: + icon: ./resources/hw-logo.png + tagline: Northstar Industrial Application's hello world application. + descriptionFile: ./resources/description.md + releaseNotes: ./resources/release-notes.md + licenseFile: ./resources/license.pdf + site: http://www.northstar-ida.com + tags: ["monitoring"] + author: + - name: Roger Wilkershank + email: rpwilkershank@northstar-ida.com + organization: + - name: Northstar Industrial Applications + site: http://northstar-ida.com +deploymentProfiles: + - type: helm + id: com-northstartida-hello-world-helm-a + components: + - name: hello-world + properties: + repository: oci://northstarida.azurecr.io/charts/hello-world + revision: 1.0.1 + wait: true +parameters: + greeting: + value: Hello + targets: + # Maps to deployment configuration param, + # e.g., helm install ... --set global.config.appGreeting="Hello" + - pointer: global.config.appGreeting + components: ["hello-world"] + greetingAddressee: + value: World + targets: + - pointer: global.config.appGreetingAddressee + components: ["hello-world"] +configuration: + sections: + - name: General Settings + settings: + - parameter: greeting + name: Greeting + description: The greeting to use. + schema: requireText + - parameter: greetingAddressee + name: Greeting Addressee + description: The person, or group, the greeting addresses. + schema: requireText + schema: + - name: requireText + dataType: string + maxLength: 45 + allowEmpty: false \ No newline at end of file diff --git a/Application-Supplier/margo-package/resources/description.md b/Application-Supplier/margo-package/resources/description.md new file mode 100644 index 0000000..3fe0391 --- /dev/null +++ b/Application-Supplier/margo-package/resources/description.md @@ -0,0 +1,2 @@ +# Application Description +This is a test application description. diff --git a/Application-Supplier/margo-package/resources/license.txt b/Application-Supplier/margo-package/resources/license.txt new file mode 100644 index 0000000..a61f0dd --- /dev/null +++ b/Application-Supplier/margo-package/resources/license.txt @@ -0,0 +1,2 @@ +# License +This is a sample license. \ No newline at end of file diff --git a/Application-Supplier/margo-package/resources/opentelemtry-logo.png b/Application-Supplier/margo-package/resources/opentelemtry-logo.png new file mode 100644 index 0000000..e69de29 diff --git a/Application-Supplier/margo-package/resources/release-notes.md b/Application-Supplier/margo-package/resources/release-notes.md new file mode 100644 index 0000000..36d6148 --- /dev/null +++ b/Application-Supplier/margo-package/resources/release-notes.md @@ -0,0 +1,3 @@ +# Release Notes + +This is a test release note document. diff --git a/Data-Generator/device-supplier/.device-scenarios b/Data-Generator/device-supplier/.device-scenarios new file mode 100644 index 0000000..e69de29 diff --git a/Data-Generator/device-supplier/TestCases/test-scenarios.json b/Data-Generator/device-supplier/TestCases/test-scenarios.json new file mode 100644 index 0000000..06911b1 --- /dev/null +++ b/Data-Generator/device-supplier/TestCases/test-scenarios.json @@ -0,0 +1,1225 @@ +[ + { + "id": "scenario-onboarding", + "name": "Device Onboarding", + "description": "Certificate retrieval plus successful and rejected onboarding flows.", + "steps": [ + { + "id": "step-1.1", + "name": "Get Root CA Certificate", + "method": "GET", + "endpoint": "/api/v1/onboarding/certificate", + "expected_status": 200, + "validations": [ + { + "field": "certificate", + "operation": "is_string" + }, + { + "field": "certificate", + "operation": "not_empty" + } + ], + "extract_context": {} + }, + { + "id": "step-1.2", + "name": "Onboard Trusted Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-1.3", + "name": "Reject Blocklisted Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "rnd-key-7f3a91b2c4d8e6" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 403, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client rejected" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities", + "name": "Capabilities Reporting", + "description": "POST and PUT capability manifests that match the spec-aligned schema.", + "steps": [ + { + "id": "step-2.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-2.1", + "name": "Report Capabilities with POST", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [ + { + "type": "camera" + } + ] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + }, + { + "id": "step-2.2", + "name": "Report Capabilities with PUT", + "method": "PUT", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "resources": { + "cpu": { + "cores": 8, + "architecture": "amd64" + }, + "memory": "32Gi", + "storage": "512Gi", + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-deployments", + "name": "Deployment Retrieval And Status", + "description": "Deployment state retrieval, cache validation, immutable artifact downloads, and status updates.", + "steps": [ + { + "id": "step-3.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-3.1", + "name": "Get Current Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "manifestVersion", + "operation": "is_number" + }, + { + "field": "bundle.mediaType", + "operation": "equals", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "bundle.digest", + "operation": "not_empty" + }, + { + "field": "deployments", + "operation": "is_array" + }, + { + "field": "deployments.0.deploymentId", + "operation": "is_string" + }, + { + "field": "bundle.url", + "operation": "not_empty" + }, + { + "field": "deployments.0.url", + "operation": "not_empty" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-3.2", + "name": "Get Deployments With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json", + "If-None-Match": "{manifestEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.3", + "name": "Download Deployment Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "bundleEtag": "_headers.ETag" + } + }, + { + "id": "step-3.4", + "name": "Download Bundle With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + "If-None-Match": "{bundleEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.5", + "name": "Download Individual Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/yaml" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.Vary", + "operation": "contains", + "value": "Accept-Encoding" + }, + { + "field": "_headers.ETag", + "operation": "contains", + "value": "{deploymentDigest}" + } + ], + "extract_context": { + "deploymentEtag": "_headers.ETag" + } + }, + { + "id": "step-3.6", + "name": "Download Individual Deployment Manifest With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + "If-None-Match": "{deploymentEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.7", + "name": "Report Deployment Status", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "acknowledgement", + "operation": "equals", + "value": "received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-onboarding-errors", + "name": "Onboarding Error Handling", + "description": "Spec-shaped 400 and 401 onboarding responses.", + "steps": [ + { + "id": "step-4.1", + "name": "Reject Onboarding With Invalid Api Version", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "v1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "apiVersion" + } + ], + "extract_context": {} + }, + { + "id": "step-4.2", + "name": "Reject Onboarding With Missing Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.3", + "name": "Reject Onboarding With Empty Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.5", + "name": "Reject Onboarding With Missing Kind", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.6", + "name": "Reject Onboarding With Wrong Kind Value", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "WrongKind", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.4", + "name": "Onboard Without Signature Succeeds", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities-errors", + "name": "Capabilities Error Handling", + "description": "Negative tests for digest, schema, role, interface, and client validation.", + "steps": [ + { + "id": "step-5.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-5.1", + "name": "Reject Capabilities With Missing Properties", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest" + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.2", + "name": "Reject Capabilities With Invalid Role", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-002", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Unknown Role" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.3", + "name": "Reject Capabilities With Invalid Interface Type", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-003", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "serial" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.4", + "name": "Reject Capabilities With Invalid Cpu Architecture", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-004", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "sparc" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.5", + "name": "Reject Capabilities With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-005", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-5.6", + "name": "Reject Capabilities Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-006", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature verification failed" + } + ], + "extract_context": {} + }, + { + "id": "step-5.7", + "name": "Reject Capabilities For Unknown Client", + "method": "POST", + "endpoint": "/api/v1/clients/not-a-real-client/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-007", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client not found" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-status-and-retrieval-errors", + "name": "Status And Retrieval Errors", + "description": "Negative coverage for deployment content negotiation, immutable resource lookup, and status schema validation.", + "steps": [ + { + "id": "step-6.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-6.1", + "name": "Get Current Deployments (Setup)", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "deployments.0.deploymentId", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-6.2", + "name": "Reject Deployments Request With Unsupported Accept Header", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/json" + }, + "expected_status": 406, + "validations": [], + "extract_context": {} + }, + { + "id": "step-6.3", + "name": "Reject Bundle Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Bundle not found" + } + ], + "extract_context": {} + }, + { + "id": "step-6.4", + "name": "Reject Deployment Manifest Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Deployment not found for digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.5", + "name": "Reject Status With Invalid State", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "done" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.6", + "name": "Reject Status With Missing Component Name", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.7", + "name": "Reject Status With Path Deployment Mismatch", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "another-deployment", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.8", + "name": "Reject Status With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.9", + "name": "Reject Status Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.10", + "name": "Reject Unsigned GET Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "skip_signing": true, + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.11", + "name": "Reject Unsigned GET Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.12", + "name": "Reject Unsigned GET Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-live-assertion-demo", + "name": "Live Assertion Demo — Dynamic Error Code", + "description": "DEMO SCENARIO: Proves server reloads assertions.json on every restart. Step 7.1 sends an invalid capabilities request (missing apiVersion) which triggers a validation error. The expected HTTP status code comes directly from error_responses.unprocessable.status_code in assertions.json. Change that one value, restart, re-run — the code changes without touching any Go code.", + "steps": [ + { + "id": "step-7.0", + "name": "Onboard Device (Demo Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-7.1", + "name": "Invalid Capabilities (missing apiVersion) — expects 422 from assertion", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "demo-device-001", + "vendor": "Demo Corp", + "modelNumber": "DEMO-X1", + "serialNumber": "SN-DEMO-001", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "amd64" }, + "memory": "8Gi", + "storage": "128Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 422, + "validations": [ + { + "field": "status", + "operation": "exists" + } + ], + "extract_context": {} + } + ] + } + +] diff --git a/Data-Generator/device-supplier/assertions.json b/Data-Generator/device-supplier/assertions.json new file mode 100644 index 0000000..842fd14 --- /dev/null +++ b/Data-Generator/device-supplier/assertions.json @@ -0,0 +1,355 @@ +{ + "rejected_certificates": [ + "rnd-key-7f3a91b2c4d8e6", + "-----BEGIN CERTIFICATE-----\nMIIDvzCCAqegAwIBAgIULI7XUGqh8u5ECDif0yPx6IVg6s4wDQYJKoZIhvcNAQEL\nBQAwbzELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxFDASBgNVBAoMC1Jldm9rZWRDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRcwFQYD\nVQQDDA5kZXZpY2UtcmV2b2tlZDAeFw0yNjA0MjIwNTIyMzVaFw0yNzA0MjIwNTIy\nMzVaMG8xCzAJBgNVBAYTAklOMQwwCgYDVQQIDANHR04xETAPBgNVBAcMCFNlY3Rv\ncjQ4MRQwEgYDVQQKDAtSZXZva2VkQ29ycDEQMA4GA1UECwwHRGV2aWNlczEXMBUG\nA1UEAwwOZGV2aWNlLXJldm9rZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQC5CTp5ocxsAsBJsvCsEn+Sl2wWJI6TD7T6feRX7Hq+H1bYe0LBa5cRgIlq\nWZrEe1RPj7lALZd8To8KLDlWqddGxIGd6N2DqQs+ZI+z+MCM2JN5PXG/BGvYVeic\nKF/Niq5FzpMmNO1yf5XaMabZLnoNL7phcXwQ2SAtJLc1jP6lMkJhoJI4Q6LgyTxw\nuK/dMCtGd5Kimy8TURRP7ImPz5KtuLaewea6e3L/4zcOWFVBqD0KwJZmTS2mCitu\nvcThDX+bR0yUhtSKKj3tArTFnVSKe2Xkl7ceI5n2LF3u0FrDUR+ndapIOK1lE732\nzWSrKJOHk6oEe8dcqunQzMWO7lvlAgMBAAGjUzBRMB0GA1UdDgQWBBTuTa56dkya\nmm7jR4bx+gVb3q8wrTAfBgNVHSMEGDAWgBTuTa56dkyamm7jR4bx+gVb3q8wrTAP\nBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCHv7LllSB2+HR5tcm6\nEDKqVuHp5TAbxYSsJcIdikN96OFHgi3PSdkRhG4yFm1hVeu5DlbrsJxBms8I4tUj\nkyBG6BzgmDQIHRbHvApWIfbSpObJ3N7SIjzrjTFzMCWJR3juGTbhgFO0WJSWXk0s\nIxtU3/FP8oXIJKghUoTG77swNcKoUk/OiP+kTiWSlViiWgnuwEfR5Oogbi9N4Hj/\nl+HzCg3KI++i0TN3X90XMf4jIkH4act4qZYOfpt9w7AoNtagXhFDcaQ6AFe6/HR+\nzBNosmP0Rpk6oLwiFUAOEJmjlUHys5CjwehCcfTkC4CzRsyf3/U0Ea2CxKTsJzGa\nDHra\n-----END CERTIFICATE-----\n" + ], + "endpoints": { + "GET_onboarding_certificate": { + "path": "/api/v1/onboarding/certificate", + "method": "GET", + "status_code": 200, + "validations": [], + "response_structure": { + "matches": [ + { + "description": "Response must contain Root CA certificate", + "json": "certificate", + "type": "string" + } + ] + } + }, + "POST_onboarding": { + "path": "/api/v1/onboarding", + "method": "POST", + "status_code": 201, + "validation_error_key": "badRequest", + "validations": [ + { + "rule_id": "onboarding-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "onboarding.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'onboarding.margo.org/v1alpha1'" + }, + { + "rule_id": "onboarding-002", + "field": "kind", + "type": "string", + "required": true, + "value": "OnboardingRequest", + "description": "kind must be exactly 'OnboardingRequest'" + }, + { + "rule_id": "onboarding-003", + "field": "certificate", + "type": "string", + "required": true, + "minLength": 1, + "description": "certificate is required and must be a non-empty base64-encoded PEM string" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must contain clientId", + "json": "clientId", + "type": "string" + } + ] + } + }, + "POST_capabilities": { + "path": "/api/v1/clients/{clientId}/capabilities", + "method": "POST", + "status_code": 201, + "validation_error_key": "unprocessable", + "validations": [ + { + "rule_id": "capabilities-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "device.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'device.margo.org/v1alpha1'" + }, + { + "rule_id": "capabilities-002", + "field": "kind", + "type": "string", + "required": true, + "value": "DeviceCapabilitiesManifest", + "description": "kind must be exactly 'DeviceCapabilitiesManifest'" + }, + { + "rule_id": "capabilities-003", + "field": "properties", + "type": "object", + "required": true, + "description": "properties field is required" + }, + { + "rule_id": "capabilities-004", + "field": "properties.id", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.id is required" + }, + { + "rule_id": "capabilities-005", + "field": "properties.vendor", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.vendor is required" + }, + { + "rule_id": "capabilities-006", + "field": "properties.modelNumber", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.modelNumber is required" + }, + { + "rule_id": "capabilities-007", + "field": "properties.serialNumber", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.serialNumber is required" + }, + { + "rule_id": "capabilities-008", + "field": "properties.roles", + "type": "array", + "required": true, + "minItems": 1, + "itemsType": "string", + "itemsEnum": [ + "Standalone Cluster", + "Cluster Leader", + "Standalone Device" + ], + "description": "properties.roles must contain at least one valid Margo device role" + }, + { + "rule_id": "capabilities-009", + "field": "properties.resources", + "type": "object", + "required": true, + "description": "properties.resources is required" + }, + { + "rule_id": "capabilities-010", + "field": "properties.resources.cpu", + "type": "object", + "required": true, + "description": "properties.resources.cpu is required" + }, + { + "rule_id": "capabilities-011", + "field": "properties.resources.cpu.cores", + "type": "number", + "required": true, + "description": "properties.resources.cpu.cores is required" + }, + { + "rule_id": "capabilities-012", + "field": "properties.resources.cpu.architecture", + "type": "string", + "required": false, + "enum": [ + "amd64", + "x86_64", + "arm64", + "arm" + ], + "description": "properties.resources.cpu.architecture must use a supported architecture value when present" + }, + { + "rule_id": "capabilities-013", + "field": "properties.resources.memory", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.resources.memory is required" + }, + { + "rule_id": "capabilities-014", + "field": "properties.resources.storage", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.resources.storage is required" + }, + { + "rule_id": "capabilities-015", + "field": "properties.resources.interfaces", + "type": "array", + "required": true, + "itemsType": "object", + "description": "properties.resources.interfaces is required" + }, + { + "rule_id": "capabilities-016", + "field": "properties.resources.interfaces.*.type", + "type": "string", + "required": true, + "enum": [ + "ethernet", + "wifi", + "cellular", + "bluetooth", + "usb", + "canbus", + "rs232" + ], + "description": "Each interface must declare a supported type" + }, + { + "rule_id": "capabilities-017", + "field": "properties.resources.peripherals", + "type": "array", + "required": true, + "itemsType": "object", + "description": "properties.resources.peripherals is required" + }, + { + "rule_id": "capabilities-018", + "field": "properties.resources.peripherals.*.type", + "type": "string", + "required": true, + "enum": [ + "gpu", + "display", + "camera", + "microphone", + "speaker" + ], + "description": "Each peripheral must declare a supported type" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must indicate success", + "json": "status", + "value": "capabilities_received" + } + ] + } + }, + "POST_status": { + "path": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "method": "POST", + "status_code": 200, + "validation_error_key": "unprocessable", + "validations": [ + { + "rule_id": "status-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "deployment.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'deployment.margo.org/v1alpha1'" + }, + { + "rule_id": "status-002", + "field": "kind", + "type": "string", + "required": true, + "value": "DeploymentStatusManifest", + "description": "kind must be exactly 'DeploymentStatusManifest'" + }, + { + "rule_id": "status-003", + "field": "deploymentId", + "type": "string", + "required": true, + "minLength": 1, + "description": "deploymentId is required" + }, + { + "rule_id": "status-004", + "field": "status", + "type": "object", + "required": true, + "description": "status object is required" + }, + { + "rule_id": "status-005", + "field": "status.state", + "type": "string", + "required": true, + "enum": [ + "pending", + "installing", + "installed", + "failed", + "removing", + "removed" + ], + "description": "status.state must be a valid deployment state" + }, + { + "rule_id": "status-006", + "field": "components", + "type": "array", + "required": true, + "itemsType": "object", + "description": "components must be an array of status entries" + }, + { + "rule_id": "status-007", + "field": "components.*.name", + "type": "string", + "required": true, + "minLength": 1, + "description": "Each component must include a name" + }, + { + "rule_id": "status-008", + "field": "components.*.state", + "type": "string", + "required": true, + "enum": [ + "pending", + "installing", + "installed", + "failed", + "removing", + "removed" + ], + "description": "Each component must include a valid state" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must acknowledge receipt", + "json": "acknowledgement", + "value": "received" + } + ] + } + } + }, + "error_responses": { + "badRequest": { + "status_code": 400, + "format": "error_string" + }, + "notFound": { + "status_code": 404, + "format": "error_string" + }, + "unprocessable": { + "status_code": 422, + "format": "validation_errors", + "status": "validation_failed" + } + } +} \ No newline at end of file diff --git a/Data-Generator/device-supplier/assertions.json.bak b/Data-Generator/device-supplier/assertions.json.bak new file mode 100644 index 0000000..c2fb4e9 --- /dev/null +++ b/Data-Generator/device-supplier/assertions.json.bak @@ -0,0 +1,354 @@ +{ + "rejected_certificates": [ + "rnd-key-7f3a91b2c4d8e6", + "-----BEGIN CERTIFICATE-----\nMIIDvzCCAqegAwIBAgIULI7XUGqh8u5ECDif0yPx6IVg6s4wDQYJKoZIhvcNAQEL\nBQAwbzELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxFDASBgNVBAoMC1Jldm9rZWRDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRcwFQYD\nVQQDDA5kZXZpY2UtcmV2b2tlZDAeFw0yNjA0MjIwNTIyMzVaFw0yNzA0MjIwNTIy\nMzVaMG8xCzAJBgNVBAYTAklOMQwwCgYDVQQIDANHR04xETAPBgNVBAcMCFNlY3Rv\ncjQ4MRQwEgYDVQQKDAtSZXZva2VkQ29ycDEQMA4GA1UECwwHRGV2aWNlczEXMBUG\nA1UEAwwOZGV2aWNlLXJldm9rZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQC5CTp5ocxsAsBJsvCsEn+Sl2wWJI6TD7T6feRX7Hq+H1bYe0LBa5cRgIlq\nWZrEe1RPj7lALZd8To8KLDlWqddGxIGd6N2DqQs+ZI+z+MCM2JN5PXG/BGvYVeic\nKF/Niq5FzpMmNO1yf5XaMabZLnoNL7phcXwQ2SAtJLc1jP6lMkJhoJI4Q6LgyTxw\nuK/dMCtGd5Kimy8TURRP7ImPz5KtuLaewea6e3L/4zcOWFVBqD0KwJZmTS2mCitu\nvcThDX+bR0yUhtSKKj3tArTFnVSKe2Xkl7ceI5n2LF3u0FrDUR+ndapIOK1lE732\nzWSrKJOHk6oEe8dcqunQzMWO7lvlAgMBAAGjUzBRMB0GA1UdDgQWBBTuTa56dkya\nmm7jR4bx+gVb3q8wrTAfBgNVHSMEGDAWgBTuTa56dkyamm7jR4bx+gVb3q8wrTAP\nBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCHv7LllSB2+HR5tcm6\nEDKqVuHp5TAbxYSsJcIdikN96OFHgi3PSdkRhG4yFm1hVeu5DlbrsJxBms8I4tUj\nkyBG6BzgmDQIHRbHvApWIfbSpObJ3N7SIjzrjTFzMCWJR3juGTbhgFO0WJSWXk0s\nIxtU3/FP8oXIJKghUoTG77swNcKoUk/OiP+kTiWSlViiWgnuwEfR5Oogbi9N4Hj/\nl+HzCg3KI++i0TN3X90XMf4jIkH4act4qZYOfpt9w7AoNtagXhFDcaQ6AFe6/HR+\nzBNosmP0Rpk6oLwiFUAOEJmjlUHys5CjwehCcfTkC4CzRsyf3/U0Ea2CxKTsJzGa\nDHra\n-----END CERTIFICATE-----\n" + ], + "endpoints": { + "GET_onboarding_certificate": { + "path": "/api/v1/onboarding/certificate", + "method": "GET", + "status_code": 200, + "validations": [], + "response_structure": { + "matches": [ + { + "description": "Response must contain Root CA certificate", + "json": "certificate", + "type": "string" + } + ] + } + }, + "POST_onboarding": { + "path": "/api/v1/onboarding", + "method": "POST", + "status_code": 201, + "validation_error_key": "badRequest", + "validations": [ + { + "rule_id": "onboarding-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "onboarding.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'onboarding.margo.org/v1alpha1'" + }, + { + "rule_id": "onboarding-002", + "field": "kind", + "type": "string", + "required": true, + "value": "OnboardingRequest", + "description": "kind must be exactly 'OnboardingRequest'" + }, + { + "rule_id": "onboarding-003", + "field": "certificate", + "type": "string", + "required": true, + "minLength": 1, + "description": "certificate is required and must be a non-empty base64-encoded PEM string" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must contain clientId", + "json": "clientId", + "type": "string" + } + ] + } + }, + "POST_capabilities": { + "path": "/api/v1/clients/{clientId}/capabilities", + "method": "POST", + "status_code": 201, + "validation_error_key": "unprocessable", + "validations": [ + { + "rule_id": "capabilities-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "device.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'device.margo.org/v1alpha1'" + }, + { + "rule_id": "capabilities-002", + "field": "kind", + "type": "string", + "required": true, + "value": "DeviceCapabilitiesManifest", + "description": "kind must be exactly 'DeviceCapabilitiesManifest'" + }, + { + "rule_id": "capabilities-003", + "field": "properties", + "type": "object", + "required": true, + "description": "properties field is required" + }, + { + "rule_id": "capabilities-004", + "field": "properties.id", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.id is required" + }, + { + "rule_id": "capabilities-005", + "field": "properties.vendor", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.vendor is required" + }, + { + "rule_id": "capabilities-006", + "field": "properties.modelNumber", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.modelNumber is required" + }, + { + "rule_id": "capabilities-007", + "field": "properties.serialNumber", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.serialNumber is required" + }, + { + "rule_id": "capabilities-008", + "field": "properties.roles", + "type": "array", + "required": true, + "itemsType": "string", + "itemsEnum": [ + "Standalone Cluster", + "Cluster Leader", + "Standalone Device" + ], + "description": "properties.roles must contain valid Margo device roles" + }, + { + "rule_id": "capabilities-009", + "field": "properties.resources", + "type": "object", + "required": true, + "description": "properties.resources is required" + }, + { + "rule_id": "capabilities-010", + "field": "properties.resources.cpu", + "type": "object", + "required": true, + "description": "properties.resources.cpu is required" + }, + { + "rule_id": "capabilities-011", + "field": "properties.resources.cpu.cores", + "type": "number", + "required": true, + "description": "properties.resources.cpu.cores is required" + }, + { + "rule_id": "capabilities-012", + "field": "properties.resources.cpu.architecture", + "type": "string", + "required": false, + "enum": [ + "amd64", + "x86_64", + "arm64", + "arm" + ], + "description": "properties.resources.cpu.architecture must use a supported architecture value when present" + }, + { + "rule_id": "capabilities-013", + "field": "properties.resources.memory", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.resources.memory is required" + }, + { + "rule_id": "capabilities-014", + "field": "properties.resources.storage", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.resources.storage is required" + }, + { + "rule_id": "capabilities-015", + "field": "properties.resources.interfaces", + "type": "array", + "required": true, + "itemsType": "object", + "description": "properties.resources.interfaces is required" + }, + { + "rule_id": "capabilities-016", + "field": "properties.resources.interfaces.*.type", + "type": "string", + "required": true, + "enum": [ + "ethernet", + "wifi", + "cellular", + "bluetooth", + "usb", + "canbus", + "rs232" + ], + "description": "Each interface must declare a supported type" + }, + { + "rule_id": "capabilities-017", + "field": "properties.resources.peripherals", + "type": "array", + "required": true, + "itemsType": "object", + "description": "properties.resources.peripherals is required" + }, + { + "rule_id": "capabilities-018", + "field": "properties.resources.peripherals.*.type", + "type": "string", + "required": true, + "enum": [ + "gpu", + "display", + "camera", + "microphone", + "speaker" + ], + "description": "Each peripheral must declare a supported type" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must indicate success", + "json": "status", + "value": "capabilities_received" + } + ] + } + }, + "POST_status": { + "path": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "method": "POST", + "status_code": 200, + "validation_error_key": "unprocessable", + "validations": [ + { + "rule_id": "status-001", + "field": "apiVersion", + "type": "string", + "required": true, + "value": "deployment.margo.org/v1alpha1", + "description": "apiVersion must be exactly 'deployment.margo.org/v1alpha1'" + }, + { + "rule_id": "status-002", + "field": "kind", + "type": "string", + "required": true, + "value": "DeploymentStatusManifest", + "description": "kind must be exactly 'DeploymentStatusManifest'" + }, + { + "rule_id": "status-003", + "field": "deploymentId", + "type": "string", + "required": true, + "minLength": 1, + "description": "deploymentId is required" + }, + { + "rule_id": "status-004", + "field": "status", + "type": "object", + "required": true, + "description": "status object is required" + }, + { + "rule_id": "status-005", + "field": "status.state", + "type": "string", + "required": true, + "enum": [ + "pending", + "installing", + "installed", + "failed", + "removing", + "removed" + ], + "description": "status.state must be a valid deployment state" + }, + { + "rule_id": "status-006", + "field": "components", + "type": "array", + "required": true, + "itemsType": "object", + "description": "components must be an array of status entries" + }, + { + "rule_id": "status-007", + "field": "components.*.name", + "type": "string", + "required": true, + "minLength": 1, + "description": "Each component must include a name" + }, + { + "rule_id": "status-008", + "field": "components.*.state", + "type": "string", + "required": true, + "enum": [ + "pending", + "installing", + "installed", + "failed", + "removing", + "removed" + ], + "description": "Each component must include a valid state" + } + ], + "response_structure": { + "matches": [ + { + "description": "Response must acknowledge receipt", + "json": "acknowledgement", + "value": "received" + } + ] + } + } + }, + "error_responses": { + "badRequest": { + "status_code": 400, + "format": "error_string" + }, + "notFound": { + "status_code": 404, + "format": "error_string" + }, + "unprocessable": { + "status_code": 422, + "format": "validation_errors", + "status": "validation_failed" + } + } +} \ No newline at end of file diff --git a/Data-Generator/device-supplier/data/clients.json b/Data-Generator/device-supplier/data/clients.json new file mode 100644 index 0000000..e78cab8 --- /dev/null +++ b/Data-Generator/device-supplier/data/clients.json @@ -0,0 +1,524 @@ +{ + "0cde90e3-5e9b-4b93-96bf-ca47dfdf4097": { + "id": "0cde90e3-5e9b-4b93-96bf-ca47dfdf4097", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.13112591Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "0fee2409-f58f-4d62-b2da-4cadd73f9434": { + "id": "0fee2409-f58f-4d62-b2da-4cadd73f9434", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.090939835Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "18cb4e9d-2ee7-47e7-b04a-8c3924ac24dd": { + "id": "18cb4e9d-2ee7-47e7-b04a-8c3924ac24dd", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.902868304Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "27e20e8c-df16-4ce9-aae2-d658d36c7d9d": { + "id": "27e20e8c-df16-4ce9-aae2-d658d36c7d9d", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.416955437Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "28b9f539-0f45-4322-b62e-1c2ad9d44064": { + "id": "28b9f539-0f45-4322-b62e-1c2ad9d44064", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.291698384Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "325f5d81-d292-44a0-b4f2-c842e9934af5": { + "id": "325f5d81-d292-44a0-b4f2-c842e9934af5", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.550089311Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "37ec2919-8dc7-4c56-8f3f-8619d985d1a9": { + "id": "37ec2919-8dc7-4c56-8f3f-8619d985d1a9", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.733647592Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "38b566f5-ba13-4e16-8ff0-5dfe57eaf758": { + "id": "38b566f5-ba13-4e16-8ff0-5dfe57eaf758", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.307342687Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "3c3eab2e-1ec1-4259-8816-524dcaccd05e": { + "id": "3c3eab2e-1ec1-4259-8816-524dcaccd05e", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.200086667Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "3f699a08-54b1-4ef1-ade3-6f2dea506138": { + "id": "3f699a08-54b1-4ef1-ade3-6f2dea506138", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.270053818Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "461f1ae7-d4e8-4925-910f-643934cf1e18": { + "id": "461f1ae7-d4e8-4925-910f-643934cf1e18", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.805425309Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "607e3c39-7d35-44b9-8e2a-0d54285f3aca": { + "id": "607e3c39-7d35-44b9-8e2a-0d54285f3aca", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.003904973Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "710dbf8c-0940-4dd2-8b01-f25a3cdfb125": { + "id": "710dbf8c-0940-4dd2-8b01-f25a3cdfb125", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.106848354Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "77f37496-fc13-4da2-83be-f6c85b5868d4": { + "id": "77f37496-fc13-4da2-83be-f6c85b5868d4", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.512005467Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "7b33287c-35d2-484f-b302-ecaa28f6960a": { + "id": "7b33287c-35d2-484f-b302-ecaa28f6960a", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.504782236Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "7b739ce5-acb5-4779-b99a-0c3f15ccca6c": { + "id": "7b739ce5-acb5-4779-b99a-0c3f15ccca6c", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.427424355Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "7bd59616-1d4a-4698-8f84-da5f7c4b3210": { + "id": "7bd59616-1d4a-4698-8f84-da5f7c4b3210", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.843020758Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "85d07408-6473-4419-8ddc-06f64809c598": { + "id": "85d07408-6473-4419-8ddc-06f64809c598", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.174303717Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "888660ba-9da1-4dba-b30c-dea415213ca0": { + "id": "888660ba-9da1-4dba-b30c-dea415213ca0", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.213187577Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "991b4908-4356-4dee-b14b-0464322057e9": { + "id": "991b4908-4356-4dee-b14b-0464322057e9", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.076749619Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "a4ccbf86-3519-493d-9252-7b970252fd2e": { + "id": "a4ccbf86-3519-493d-9252-7b970252fd2e", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.193167908Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "a5a8d537-62ac-422e-bd33-5062a63062e3": { + "id": "a5a8d537-62ac-422e-bd33-5062a63062e3", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.184483345Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "a66ba65c-8654-43b6-98bf-5348eccdba18": { + "id": "a66ba65c-8654-43b6-98bf-5348eccdba18", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.44303134Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "a856427d-e7cd-4dbc-bb96-72953c9103a0": { + "id": "a856427d-e7cd-4dbc-bb96-72953c9103a0", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.173968831Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "afa42ed4-c94e-428f-bf33-5fc3820c93f2": { + "id": "afa42ed4-c94e-428f-bf33-5fc3820c93f2", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.198805313Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "b1dcc517-eeba-4d3d-909a-f69d52390b0e": { + "id": "b1dcc517-eeba-4d3d-909a-f69d52390b0e", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.362916132Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "b62f47c7-2b0c-482b-86c7-82dec788083b": { + "id": "b62f47c7-2b0c-482b-86c7-82dec788083b", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.190264291Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "b6d4c4eb-ddbb-4356-8bda-2acfc786efaa": { + "id": "b6d4c4eb-ddbb-4356-8bda-2acfc786efaa", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.116559702Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "bb47714b-c3ef-4bf6-a326-805af13248f5": { + "id": "bb47714b-c3ef-4bf6-a326-805af13248f5", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:41:55.234923838Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "bffa4b9a-9b1f-460a-b1a3-bb6112ff7656": { + "id": "bffa4b9a-9b1f-460a-b1a3-bb6112ff7656", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.707748441Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "c3dbebf2-b574-4e61-9d04-7a6879b21b9f": { + "id": "c3dbebf2-b574-4e61-9d04-7a6879b21b9f", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.10237581Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "d0f111ef-92ec-44d4-8de2-593ef5902418": { + "id": "d0f111ef-92ec-44d4-8de2-593ef5902418", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:32.264141067Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "d10604d5-b89c-46e0-9ba3-9267b3dc836d": { + "id": "d10604d5-b89c-46e0-9ba3-9267b3dc836d", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.168445855Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "d5736124-7370-4a97-b8e5-b231a3643639": { + "id": "d5736124-7370-4a97-b8e5-b231a3643639", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.096922518Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "d806ad0f-e12a-4c78-8593-c84d238ee42e": { + "id": "d806ad0f-e12a-4c78-8593-c84d238ee42e", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.013777799Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "e3a2a479-60a7-4fa0-b7d1-86e070272db3": { + "id": "e3a2a479-60a7-4fa0-b7d1-86e070272db3", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T16:56:12.609739609Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "e697c196-265e-4d43-9d8a-a9bae7b3b3af": { + "id": "e697c196-265e-4d43-9d8a-a9bae7b3b3af", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.270438429Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "e8561e06-caee-4842-99af-7246bdd32d2c": { + "id": "e8561e06-caee-4842-99af-7246bdd32d2c", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.028055714Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "f2c9691d-bb58-454c-9e99-e68221d2629e": { + "id": "f2c9691d-bb58-454c-9e99-e68221d2629e", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:38.13365461Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "fbd1ca79-852d-4a1a-af03-9bd477bb355c": { + "id": "fbd1ca79-852d-4a1a-af03-9bd477bb355c", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.799984004Z", + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "fe89066b-5253-4490-b4ea-b81275f4a12f": { + "id": "fe89066b-5253-4490-b4ea-b81275f4a12f", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T10:49:55.087574731Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + }, + "ff38de1a-9a43-46f1-b60d-db2e4df4c500": { + "id": "ff38de1a-9a43-46f1-b60d-db2e4df4c500", + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDsTCCApmgAwIBAgIUbBfLB53Qprht2ClgWj3a93JSICkwDQYJKoZIhvcNAQEL\nBQAwaDELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9y\nNDgxETAPBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQD\nDApkZXZpY2UtMDAxMB4XDTI2MDUxMjA5MzcwMVoXDTI3MDUxMjA5MzcwMVowaDEL\nMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgxETAP\nBgNVBAoMCEFjbWVDb3JwMRAwDgYDVQQLDAdEZXZpY2VzMRMwEQYDVQQDDApkZXZp\nY2UtMDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhNSPQiuAr+q\nDCHfTYgP6e2K045FPq72/s3TZrCtCLrKnW9BkXlgI8XXo79XB1cb0uADsgxIywIk\nNYB+EBZJ/8AtS8n5WZRnXBeyhxeRuxUOiKeQlRTT4vvFAXpHlw0wAi9fmVHLyNRt\nyVhi8qEkBFrUsL+yqK3G2uQu388dY2keJTv/iTrrfVFIzBR4XIAv+Ak2yBiwpq89\n0nXF/mZojir7WMnaFxuiJb+ZV0ISq6ELmvcMypXRhCjQo1z28GQm4oV6SoCVRxJv\nCAVIZl7jKD5U3hOZ4vZzoYLbG4wO5eOBu6laMGUzjkK2Y5MVZtt3P+0vEH7wwIDe\nkaB2Tt+DiwIDAQABo1MwUTAdBgNVHQ4EFgQUeM6bRXDyyKPYHVui0qmRGgCKth0w\nHwYDVR0jBBgwFoAUeM6bRXDyyKPYHVui0qmRGgCKth0wDwYDVR0TAQH/BAUwAwEB\n/zANBgkqhkiG9w0BAQsFAAOCAQEAXZIFVTuI37MmiQTUMBiqaNJhuJMYSCvQpKC/\n5bUnNLKxCmXNsP/4Tk0HafJKzf87kdv19H7SxY8qMg4NtDE5BLgirvoZXlCLrbQk\nfIWQoMQXnrF5h85XcHv7FLtVjF2AtIxgQXY6YU1BpnmsyUxS8G01MpYk8kE6EXHA\nIDtf/odb9yTDL8tDdZPVtiLIfG44ZYv0nEHoOoHXSraRIPK9B3ticAuOCS2BWYhg\ntaIQyiok8s2N8yw8cgkQENZBmrpwSOt/JqgqJfCFgID63tDAYtaFyWVfRM/qD5QL\nmauNF0SdRvAXtad1ntOj51uiHVWxkx1zc0B/35cUVH1Uuqw1+g==\n-----END CERTIFICATE-----\n", + "onboarded_at": "2026-05-22T06:00:02.718247014Z", + "capabilities": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "modelNumber": "ACM-XYZ", + "resources": { + "cpu": { + "architecture": "amd64", + "cores": 8 + }, + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "memory": "32Gi", + "peripherals": [], + "storage": "512Gi" + }, + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "serialNumber": "SN-12345", + "vendor": "Acme Corp" + } + }, + "deployments": [ + "a3e2f5dc-912e-494f-8395-52cf3769bc06" + ] + } +} \ No newline at end of file diff --git a/Data-Generator/device-supplier/data/deployments.json b/Data-Generator/device-supplier/data/deployments.json new file mode 100644 index 0000000..640eacb --- /dev/null +++ b/Data-Generator/device-supplier/data/deployments.json @@ -0,0 +1,302 @@ +{ + "0cde90e3-5e9b-4b93-96bf-ca47dfdf4097:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "0cde90e3-5e9b-4b93-96bf-ca47dfdf4097", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "0fee2409-f58f-4d62-b2da-4cadd73f9434:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "0fee2409-f58f-4d62-b2da-4cadd73f9434", + "status_history": [] + }, + "18cb4e9d-2ee7-47e7-b04a-8c3924ac24dd:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "18cb4e9d-2ee7-47e7-b04a-8c3924ac24dd", + "status_history": [] + }, + "27e20e8c-df16-4ce9-aae2-d658d36c7d9d:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "27e20e8c-df16-4ce9-aae2-d658d36c7d9d", + "status_history": [] + }, + "28b9f539-0f45-4322-b62e-1c2ad9d44064:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "28b9f539-0f45-4322-b62e-1c2ad9d44064", + "status_history": [] + }, + "325f5d81-d292-44a0-b4f2-c842e9934af5:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "325f5d81-d292-44a0-b4f2-c842e9934af5", + "status_history": [] + }, + "37ec2919-8dc7-4c56-8f3f-8619d985d1a9:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "37ec2919-8dc7-4c56-8f3f-8619d985d1a9", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "38b566f5-ba13-4e16-8ff0-5dfe57eaf758:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "38b566f5-ba13-4e16-8ff0-5dfe57eaf758", + "status_history": [] + }, + "3c3eab2e-1ec1-4259-8816-524dcaccd05e:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "3c3eab2e-1ec1-4259-8816-524dcaccd05e", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "3f699a08-54b1-4ef1-ade3-6f2dea506138:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "3f699a08-54b1-4ef1-ade3-6f2dea506138", + "status_history": [] + }, + "461f1ae7-d4e8-4925-910f-643934cf1e18:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "461f1ae7-d4e8-4925-910f-643934cf1e18", + "status_history": [] + }, + "607e3c39-7d35-44b9-8e2a-0d54285f3aca:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "607e3c39-7d35-44b9-8e2a-0d54285f3aca", + "status_history": [] + }, + "710dbf8c-0940-4dd2-8b01-f25a3cdfb125:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "710dbf8c-0940-4dd2-8b01-f25a3cdfb125", + "status_history": [] + }, + "77f37496-fc13-4da2-83be-f6c85b5868d4:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "77f37496-fc13-4da2-83be-f6c85b5868d4", + "status_history": [] + }, + "7b33287c-35d2-484f-b302-ecaa28f6960a:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "7b33287c-35d2-484f-b302-ecaa28f6960a", + "status_history": [] + }, + "7b739ce5-acb5-4779-b99a-0c3f15ccca6c:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "7b739ce5-acb5-4779-b99a-0c3f15ccca6c", + "status_history": [] + }, + "7bd59616-1d4a-4698-8f84-da5f7c4b3210:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "7bd59616-1d4a-4698-8f84-da5f7c4b3210", + "status_history": [] + }, + "85d07408-6473-4419-8ddc-06f64809c598:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "85d07408-6473-4419-8ddc-06f64809c598", + "status_history": [] + }, + "888660ba-9da1-4dba-b30c-dea415213ca0:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "888660ba-9da1-4dba-b30c-dea415213ca0", + "status_history": [] + }, + "991b4908-4356-4dee-b14b-0464322057e9:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "991b4908-4356-4dee-b14b-0464322057e9", + "status_history": [] + }, + "a4ccbf86-3519-493d-9252-7b970252fd2e:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "a4ccbf86-3519-493d-9252-7b970252fd2e", + "status_history": [] + }, + "a5a8d537-62ac-422e-bd33-5062a63062e3:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "a5a8d537-62ac-422e-bd33-5062a63062e3", + "status_history": [] + }, + "a66ba65c-8654-43b6-98bf-5348eccdba18:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "a66ba65c-8654-43b6-98bf-5348eccdba18", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "a856427d-e7cd-4dbc-bb96-72953c9103a0:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "a856427d-e7cd-4dbc-bb96-72953c9103a0", + "status_history": [] + }, + "afa42ed4-c94e-428f-bf33-5fc3820c93f2:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "afa42ed4-c94e-428f-bf33-5fc3820c93f2", + "status_history": [] + }, + "b1dcc517-eeba-4d3d-909a-f69d52390b0e:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "b1dcc517-eeba-4d3d-909a-f69d52390b0e", + "status_history": [] + }, + "b62f47c7-2b0c-482b-86c7-82dec788083b:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "b62f47c7-2b0c-482b-86c7-82dec788083b", + "status_history": [] + }, + "b6d4c4eb-ddbb-4356-8bda-2acfc786efaa:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "b6d4c4eb-ddbb-4356-8bda-2acfc786efaa", + "status_history": [] + }, + "bb47714b-c3ef-4bf6-a326-805af13248f5:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "bb47714b-c3ef-4bf6-a326-805af13248f5", + "status_history": [] + }, + "bffa4b9a-9b1f-460a-b1a3-bb6112ff7656:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "bffa4b9a-9b1f-460a-b1a3-bb6112ff7656", + "status_history": [] + }, + "c3dbebf2-b574-4e61-9d04-7a6879b21b9f:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "c3dbebf2-b574-4e61-9d04-7a6879b21b9f", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "d0f111ef-92ec-44d4-8de2-593ef5902418:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "d0f111ef-92ec-44d4-8de2-593ef5902418", + "status_history": [] + }, + "d10604d5-b89c-46e0-9ba3-9267b3dc836d:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "d10604d5-b89c-46e0-9ba3-9267b3dc836d", + "status_history": [] + }, + "d5736124-7370-4a97-b8e5-b231a3643639:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "d5736124-7370-4a97-b8e5-b231a3643639", + "status_history": [] + }, + "d806ad0f-e12a-4c78-8593-c84d238ee42e:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "d806ad0f-e12a-4c78-8593-c84d238ee42e", + "status_history": [] + }, + "e3a2a479-60a7-4fa0-b7d1-86e070272db3:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "e3a2a479-60a7-4fa0-b7d1-86e070272db3", + "status_history": [] + }, + "e697c196-265e-4d43-9d8a-a9bae7b3b3af:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "e697c196-265e-4d43-9d8a-a9bae7b3b3af", + "status_history": [] + }, + "e8561e06-caee-4842-99af-7246bdd32d2c:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "e8561e06-caee-4842-99af-7246bdd32d2c", + "status_history": [ + { + "apiVersion": "deployment.margo.org/v1alpha1", + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ], + "deploymentId": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "kind": "DeploymentStatusManifest", + "status": { + "state": "installed" + } + } + ] + }, + "f2c9691d-bb58-454c-9e99-e68221d2629e:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "f2c9691d-bb58-454c-9e99-e68221d2629e", + "status_history": [] + }, + "fbd1ca79-852d-4a1a-af03-9bd477bb355c:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "fbd1ca79-852d-4a1a-af03-9bd477bb355c", + "status_history": [] + }, + "fe89066b-5253-4490-b4ea-b81275f4a12f:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "fe89066b-5253-4490-b4ea-b81275f4a12f", + "status_history": [] + }, + "ff38de1a-9a43-46f1-b60d-db2e4df4c500:a3e2f5dc-912e-494f-8395-52cf3769bc06": { + "id": "a3e2f5dc-912e-494f-8395-52cf3769bc06", + "client_id": "ff38de1a-9a43-46f1-b60d-db2e4df4c500", + "status_history": [] + } +} \ No newline at end of file diff --git a/Data-Generator/device-supplier/deployment-template.yaml b/Data-Generator/device-supplier/deployment-template.yaml new file mode 100644 index 0000000..631f7cc --- /dev/null +++ b/Data-Generator/device-supplier/deployment-template.yaml @@ -0,0 +1,16 @@ +apiVersion: margo.org/v1alpha1 +kind: ApplicationDeployment +metadata: + name: {{deploymentId}} + annotations: + id: {{deploymentId}} +spec: + appPackageRef: + id: compose-sample + deploymentProfile: + type: compose + components: + - name: compose-sample + properties: + packageLocation: https://raw.githubusercontent.com/nginx-proxy/nginx-proxy/refs/heads/main/docker-compose.yml + wait: true diff --git a/Data-Generator/device-supplier/groups/bronze/group.json b/Data-Generator/device-supplier/groups/bronze/group.json new file mode 100644 index 0000000..262678e --- /dev/null +++ b/Data-Generator/device-supplier/groups/bronze/group.json @@ -0,0 +1,71 @@ +{ + "name": "bronze", + "version": "1.0.0", + "persona": "device-supplier", + "description": "ng", + "FolderPath": [ + "testcases/user1Device", + "testcases/user2Device" + ], + "flexibleOrder": false, + "testCases": [ + "demo-device-001", + "device-001", + "device-002", + "device-003", + "device-004", + "device-005", + "device-006", + "device-007", + "scenario-capabilities", + "scenario-capabilities-errors", + "scenario-deployments", + "scenario-live-assertion-demo", + "scenario-onboarding", + "scenario-onboarding-errors", + "scenario-status-and-retrieval-errors", + "step-1.1", + "step-1.2", + "step-1.3", + "step-2.0", + "step-2.1", + "step-2.2", + "step-3.0", + "step-3.1", + "step-3.2", + "step-3.3", + "step-3.4", + "step-3.5", + "step-3.6", + "step-3.7", + "step-4.1", + "step-4.2", + "step-4.3", + "step-4.4", + "step-4.5", + "step-4.6", + "step-5.0", + "step-5.1", + "step-5.2", + "step-5.3", + "step-5.4", + "step-5.5", + "step-5.6", + "step-5.7", + "step-6.0", + "step-6.1", + "step-6.10", + "step-6.11", + "step-6.12", + "step-6.2", + "step-6.3", + "step-6.4", + "step-6.5", + "step-6.6", + "step-6.7", + "step-6.8", + "step-6.9", + "step-7.0", + "step-7.1" + ] +} diff --git a/Data-Generator/device-supplier/groups/bronze/test-scenarios.json b/Data-Generator/device-supplier/groups/bronze/test-scenarios.json new file mode 100644 index 0000000..06911b1 --- /dev/null +++ b/Data-Generator/device-supplier/groups/bronze/test-scenarios.json @@ -0,0 +1,1225 @@ +[ + { + "id": "scenario-onboarding", + "name": "Device Onboarding", + "description": "Certificate retrieval plus successful and rejected onboarding flows.", + "steps": [ + { + "id": "step-1.1", + "name": "Get Root CA Certificate", + "method": "GET", + "endpoint": "/api/v1/onboarding/certificate", + "expected_status": 200, + "validations": [ + { + "field": "certificate", + "operation": "is_string" + }, + { + "field": "certificate", + "operation": "not_empty" + } + ], + "extract_context": {} + }, + { + "id": "step-1.2", + "name": "Onboard Trusted Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-1.3", + "name": "Reject Blocklisted Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "rnd-key-7f3a91b2c4d8e6" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 403, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client rejected" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities", + "name": "Capabilities Reporting", + "description": "POST and PUT capability manifests that match the spec-aligned schema.", + "steps": [ + { + "id": "step-2.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-2.1", + "name": "Report Capabilities with POST", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [ + { + "type": "camera" + } + ] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + }, + { + "id": "step-2.2", + "name": "Report Capabilities with PUT", + "method": "PUT", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "resources": { + "cpu": { + "cores": 8, + "architecture": "amd64" + }, + "memory": "32Gi", + "storage": "512Gi", + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-deployments", + "name": "Deployment Retrieval And Status", + "description": "Deployment state retrieval, cache validation, immutable artifact downloads, and status updates.", + "steps": [ + { + "id": "step-3.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-3.1", + "name": "Get Current Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "manifestVersion", + "operation": "is_number" + }, + { + "field": "bundle.mediaType", + "operation": "equals", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "bundle.digest", + "operation": "not_empty" + }, + { + "field": "deployments", + "operation": "is_array" + }, + { + "field": "deployments.0.deploymentId", + "operation": "is_string" + }, + { + "field": "bundle.url", + "operation": "not_empty" + }, + { + "field": "deployments.0.url", + "operation": "not_empty" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-3.2", + "name": "Get Deployments With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json", + "If-None-Match": "{manifestEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.3", + "name": "Download Deployment Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "bundleEtag": "_headers.ETag" + } + }, + { + "id": "step-3.4", + "name": "Download Bundle With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + "If-None-Match": "{bundleEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.5", + "name": "Download Individual Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/yaml" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.Vary", + "operation": "contains", + "value": "Accept-Encoding" + }, + { + "field": "_headers.ETag", + "operation": "contains", + "value": "{deploymentDigest}" + } + ], + "extract_context": { + "deploymentEtag": "_headers.ETag" + } + }, + { + "id": "step-3.6", + "name": "Download Individual Deployment Manifest With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + "If-None-Match": "{deploymentEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.7", + "name": "Report Deployment Status", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "acknowledgement", + "operation": "equals", + "value": "received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-onboarding-errors", + "name": "Onboarding Error Handling", + "description": "Spec-shaped 400 and 401 onboarding responses.", + "steps": [ + { + "id": "step-4.1", + "name": "Reject Onboarding With Invalid Api Version", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "v1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "apiVersion" + } + ], + "extract_context": {} + }, + { + "id": "step-4.2", + "name": "Reject Onboarding With Missing Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.3", + "name": "Reject Onboarding With Empty Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.5", + "name": "Reject Onboarding With Missing Kind", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.6", + "name": "Reject Onboarding With Wrong Kind Value", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "WrongKind", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.4", + "name": "Onboard Without Signature Succeeds", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities-errors", + "name": "Capabilities Error Handling", + "description": "Negative tests for digest, schema, role, interface, and client validation.", + "steps": [ + { + "id": "step-5.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-5.1", + "name": "Reject Capabilities With Missing Properties", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest" + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.2", + "name": "Reject Capabilities With Invalid Role", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-002", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Unknown Role" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.3", + "name": "Reject Capabilities With Invalid Interface Type", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-003", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "serial" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.4", + "name": "Reject Capabilities With Invalid Cpu Architecture", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-004", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "sparc" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.5", + "name": "Reject Capabilities With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-005", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-5.6", + "name": "Reject Capabilities Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-006", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature verification failed" + } + ], + "extract_context": {} + }, + { + "id": "step-5.7", + "name": "Reject Capabilities For Unknown Client", + "method": "POST", + "endpoint": "/api/v1/clients/not-a-real-client/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-007", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client not found" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-status-and-retrieval-errors", + "name": "Status And Retrieval Errors", + "description": "Negative coverage for deployment content negotiation, immutable resource lookup, and status schema validation.", + "steps": [ + { + "id": "step-6.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-6.1", + "name": "Get Current Deployments (Setup)", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "deployments.0.deploymentId", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-6.2", + "name": "Reject Deployments Request With Unsupported Accept Header", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/json" + }, + "expected_status": 406, + "validations": [], + "extract_context": {} + }, + { + "id": "step-6.3", + "name": "Reject Bundle Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Bundle not found" + } + ], + "extract_context": {} + }, + { + "id": "step-6.4", + "name": "Reject Deployment Manifest Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Deployment not found for digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.5", + "name": "Reject Status With Invalid State", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "done" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.6", + "name": "Reject Status With Missing Component Name", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.7", + "name": "Reject Status With Path Deployment Mismatch", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "another-deployment", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.8", + "name": "Reject Status With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.9", + "name": "Reject Status Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.10", + "name": "Reject Unsigned GET Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "skip_signing": true, + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.11", + "name": "Reject Unsigned GET Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.12", + "name": "Reject Unsigned GET Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-live-assertion-demo", + "name": "Live Assertion Demo — Dynamic Error Code", + "description": "DEMO SCENARIO: Proves server reloads assertions.json on every restart. Step 7.1 sends an invalid capabilities request (missing apiVersion) which triggers a validation error. The expected HTTP status code comes directly from error_responses.unprocessable.status_code in assertions.json. Change that one value, restart, re-run — the code changes without touching any Go code.", + "steps": [ + { + "id": "step-7.0", + "name": "Onboard Device (Demo Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-7.1", + "name": "Invalid Capabilities (missing apiVersion) — expects 422 from assertion", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "demo-device-001", + "vendor": "Demo Corp", + "modelNumber": "DEMO-X1", + "serialNumber": "SN-DEMO-001", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "amd64" }, + "memory": "8Gi", + "storage": "128Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 422, + "validations": [ + { + "field": "status", + "operation": "exists" + } + ], + "extract_context": {} + } + ] + } + +] diff --git a/Data-Generator/device-supplier/groups/core/group.json b/Data-Generator/device-supplier/groups/core/group.json new file mode 100644 index 0000000..be7554f --- /dev/null +++ b/Data-Generator/device-supplier/groups/core/group.json @@ -0,0 +1,11 @@ +{ + "name": "core", + "version": "1.0.0-rc.2", + "persona": "device-supplier", + "description": "Generic/positive/negative/edge coverage of Device Supplier conformance requirements not exercised by the other groups: device-role capability variants (Standalone Cluster vs Standalone Device), invalid supportedDeploymentTypes/supportedRuntimes enum values, a malformed cpus[] entry, default content negotiation when Accept is omitted, and the zero-deployments manifest edge case.", + "FolderPath": [ + "testcases/device-core" + ], + "flexibleOrder": false, + "testCases": [] +} diff --git a/Data-Generator/device-supplier/groups/diamond/group.json b/Data-Generator/device-supplier/groups/diamond/group.json new file mode 100644 index 0000000..4f2bf68 --- /dev/null +++ b/Data-Generator/device-supplier/groups/diamond/group.json @@ -0,0 +1,55 @@ +{ + "name": "diamond", + "version": "v1.0.0", + "persona": "device-supplier", + "description": "v1.0.0", + "FolderPath": [ + "testcases/user2" + ], + "testCases": [ + "045403b4-89ac-4c08-9146-7a92040c3476", + "04562ab9-d47a-47c9-81c5-03301acae6bd", + "0b4b5451-41c9-4155-9724-e1a8fe863ca0", + "10811a89-c9bf-4b22-9e7e-9a34eb45a054", + "1a5d47ce-5f1a-4f7a-ad56-061e87183fa6", + "1f66d6e9-4a85-4ceb-a693-f1a43e5ca2c8", + "1ff8dae9-06d3-486e-b156-5e2cd80e7a56", + "2dea28c5-00e4-4cab-b6e2-d199cea1cfe4", + "342e096c-893c-4f76-b6d6-f0bbb1c2066f", + "387af239-f4e4-429b-9584-90c414e0a7c4", + "3e26c5c6-ae6e-4abb-9012-84cb05939f62", + "462ffe48-2af8-46c2-9781-ccbfa0860d0c", + "469d2b44-34c0-4bba-ad20-4c7259c22031", + "4934b7a1-d099-4702-afb6-9bb4681b4713", + "55b7012f-aa47-4c20-903d-79c301ab8de9", + "5f847811-b779-4c72-ab6d-8e583b3950ac", + "5ffd6386-9b89-4bb4-8f4d-2ed8b85a381f", + "6a805ce8-58f8-4845-81f6-fa3322bd8f9b", + "6ec4dc6e-ea73-4528-85e7-7880e7e9e816", + "7392e234-6f45-43e2-a027-b0a86bad517e", + "7ccf9c54-36ea-42e2-b4fe-f6e00910c944", + "7e655ed3-f370-463d-b506-630fb0defdbf", + "83aa0550-a4aa-451b-be6f-37600ab6a414", + "87d8faa5-25fe-442b-bda0-2fc0ddf983b6", + "8ab3b05f-46c4-4c50-8104-8982f060f1ce", + "8d5d19ed-a5c2-4216-8fd1-c50b05aadefe", + "8df9329e-5177-4d12-b05c-2bc81d63a76a", + "92d987db-beaa-467c-97dd-059c18556681", + "98f57b60-ffd9-4832-a944-0db7ce1ecede", + "9bed5895-ee56-417f-96c8-5d2fd3c7dd2d", + "a04696b2-7bff-4460-8d8d-b992f193b4db", + "a5efd1c1-9806-4aac-9901-5d87b45424c1", + "aa4cfb2b-3d00-420b-a479-0c8ce289f2ec", + "b560e49d-169f-40f7-b1ec-07620a7620a9", + "c006a5d9-d966-4b2c-b21f-e02a03bf5be5", + "c02c5cde-8707-45d1-b5b5-fb9238efb3ac", + "c2706fbd-e147-4a78-a04b-79c86c46387c", + "c37cb9e4-24a5-4106-bbbb-a48feaf4bee1", + "ca621765-37e6-44b8-b846-9635b37bb1ba", + "cc86f6b1-287a-4e63-bbaa-147e162fb23f", + "d3cae471-6d2e-4ef0-9569-6152f8d722ff", + "e71e3fb8-62a3-4e2b-9511-0f8a3b52083e", + "ed4a34b9-7c61-4289-885e-5b37cc02b01e", + "f5bc7d9f-965f-4c6b-a4cb-398b3c1aff78" + ] +} diff --git a/Data-Generator/device-supplier/groups/flex-order/group.json b/Data-Generator/device-supplier/groups/flex-order/group.json new file mode 100644 index 0000000..629ae67 --- /dev/null +++ b/Data-Generator/device-supplier/groups/flex-order/group.json @@ -0,0 +1,11 @@ +{ + "name": "flex-order", + "version": "1.0.0-rc.2", + "persona": "device-supplier", + "description": "Regenerated via CLI-1 (E2E verification pass)", + "FolderPath": [ + "testcases/device-supplier-flexible-order" + ], + "flexibleOrder": true, + "testCases": [] +} diff --git a/Data-Generator/device-supplier/groups/gold/group.json b/Data-Generator/device-supplier/groups/gold/group.json new file mode 100644 index 0000000..9b5d685 --- /dev/null +++ b/Data-Generator/device-supplier/groups/gold/group.json @@ -0,0 +1,72 @@ +{ + "name": "gold", + "version": "v1.0.0", + "persona": "device-supplier", + "description": "v1.0.0", + "FolderPath": [ + "testcases/user1Device", + "testcases/user2Device" + ], + "testCases": [ + "demo-device-001", + "device-001", + "device-002", + "device-003", + "device-004", + "device-005", + "device-006", + "device-007", + "device-invalid-mem", + "scenario-capabilities", + "scenario-capabilities-errors", + "scenario-deployments", + "scenario-live-assertion-demo", + "scenario-onboarding", + "scenario-onboarding-errors", + "scenario-status-and-retrieval-errors", + "step-1.1", + "step-1.2", + "step-1.3", + "step-2.0", + "step-2.1", + "step-2.2", + "step-3.0", + "step-3.1", + "step-3.2", + "step-3.3", + "step-3.4", + "step-3.5", + "step-3.6", + "step-3.7", + "step-4.1", + "step-4.2", + "step-4.3", + "step-4.4", + "step-4.5", + "step-4.6", + "step-5.0", + "step-5.1", + "step-5.2", + "step-5.3", + "step-5.4", + "step-5.5", + "step-5.6", + "step-5.7", + "step-6.0", + "step-6.1", + "step-6.10", + "step-6.11", + "step-6.12", + "step-6.2", + "step-6.3", + "step-6.4", + "step-6.5", + "step-6.6", + "step-6.7", + "step-6.8", + "step-6.9", + "step-7.0", + "step-7.1", + "step-custom-1" + ] +} diff --git a/Data-Generator/device-supplier/groups/newgrp-devicesupplier1/group.json b/Data-Generator/device-supplier/groups/newgrp-devicesupplier1/group.json new file mode 100644 index 0000000..4494eee --- /dev/null +++ b/Data-Generator/device-supplier/groups/newgrp-devicesupplier1/group.json @@ -0,0 +1,62 @@ +{ + "name": "newgrp-devicesupplier1", + "version": "1.1.3", + "persona": "device-supplier", + "description": "existing grp", + "FolderPath": [ + "testcases/user1Device" + ], + "flexibleOrder": false, + "testCases": [ + "scenario-capabilities", + "scenario-capabilities-errors", + "scenario-deployments", + "scenario-live-assertion-demo", + "scenario-onboarding", + "scenario-onboarding-errors", + "scenario-status-and-retrieval-errors", + "step-1.1", + "step-1.2", + "step-1.3", + "step-2.0", + "step-2.1", + "step-2.2", + "step-3.0", + "step-3.1", + "step-3.2", + "step-3.3", + "step-3.4", + "step-3.5", + "step-3.6", + "step-3.7", + "step-4.1", + "step-4.2", + "step-4.3", + "step-4.4", + "step-4.5", + "step-4.6", + "step-5.0", + "step-5.1", + "step-5.2", + "step-5.3", + "step-5.4", + "step-5.5", + "step-5.6", + "step-5.7", + "step-6.0", + "step-6.1", + "step-6.10", + "step-6.11", + "step-6.12", + "step-6.2", + "step-6.3", + "step-6.4", + "step-6.5", + "step-6.6", + "step-6.7", + "step-6.8", + "step-6.9", + "step-7.0", + "step-7.1" + ] +} diff --git a/Data-Generator/device-supplier/groups/silver/group.json b/Data-Generator/device-supplier/groups/silver/group.json new file mode 100644 index 0000000..97c0a4e --- /dev/null +++ b/Data-Generator/device-supplier/groups/silver/group.json @@ -0,0 +1,72 @@ +{ + "name": "silver", + "version": "1.0.0-rc.2", + "persona": "device-supplier", + "description": "Regenerated via CLI-1 (E2E verification pass)", + "FolderPath": [ + "testcases/user2Device" + ], + "flexibleOrder": false, + "testCases": [ + "demo-device-001", + "device-001", + "device-002", + "device-003", + "device-004", + "device-005", + "device-006", + "device-007", + "device-invalid-mem", + "scenario-capabilities", + "scenario-capabilities-errors", + "scenario-deployments", + "scenario-live-assertion-demo", + "scenario-onboarding", + "scenario-onboarding-errors", + "scenario-status-and-retrieval-errors", + "step-1.1", + "step-1.2", + "step-1.3", + "step-2.0", + "step-2.1", + "step-2.2", + "step-3.0", + "step-3.1", + "step-3.2", + "step-3.3", + "step-3.4", + "step-3.5", + "step-3.6", + "step-3.7", + "step-4.1", + "step-4.2", + "step-4.3", + "step-4.4", + "step-4.5", + "step-4.6", + "step-5.0", + "step-5.1", + "step-5.2", + "step-5.3", + "step-5.4", + "step-5.5", + "step-5.6", + "step-5.7", + "step-6.0", + "step-6.1", + "step-6.10", + "step-6.11", + "step-6.12", + "step-6.2", + "step-6.3", + "step-6.4", + "step-6.5", + "step-6.6", + "step-6.7", + "step-6.8", + "step-6.9", + "step-7.0", + "step-7.1", + "step-custom-1" + ] +} diff --git a/Data-Generator/device-supplier/test-scenarios.json b/Data-Generator/device-supplier/test-scenarios.json new file mode 100644 index 0000000..06911b1 --- /dev/null +++ b/Data-Generator/device-supplier/test-scenarios.json @@ -0,0 +1,1225 @@ +[ + { + "id": "scenario-onboarding", + "name": "Device Onboarding", + "description": "Certificate retrieval plus successful and rejected onboarding flows.", + "steps": [ + { + "id": "step-1.1", + "name": "Get Root CA Certificate", + "method": "GET", + "endpoint": "/api/v1/onboarding/certificate", + "expected_status": 200, + "validations": [ + { + "field": "certificate", + "operation": "is_string" + }, + { + "field": "certificate", + "operation": "not_empty" + } + ], + "extract_context": {} + }, + { + "id": "step-1.2", + "name": "Onboard Trusted Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-1.3", + "name": "Reject Blocklisted Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "rnd-key-7f3a91b2c4d8e6" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 403, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client rejected" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities", + "name": "Capabilities Reporting", + "description": "POST and PUT capability manifests that match the spec-aligned schema.", + "steps": [ + { + "id": "step-2.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-2.1", + "name": "Report Capabilities with POST", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [ + { + "type": "camera" + } + ] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + }, + { + "id": "step-2.2", + "name": "Report Capabilities with PUT", + "method": "PUT", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device", + "Cluster Leader" + ], + "resources": { + "cpu": { + "cores": 8, + "architecture": "amd64" + }, + "memory": "32Gi", + "storage": "512Gi", + "interfaces": [ + { + "type": "ethernet" + }, + { + "type": "wifi" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "status", + "operation": "equals", + "value": "capabilities_received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-deployments", + "name": "Deployment Retrieval And Status", + "description": "Deployment state retrieval, cache validation, immutable artifact downloads, and status updates.", + "steps": [ + { + "id": "step-3.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-3.1", + "name": "Get Current Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "manifestVersion", + "operation": "is_number" + }, + { + "field": "bundle.mediaType", + "operation": "equals", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "bundle.digest", + "operation": "not_empty" + }, + { + "field": "deployments", + "operation": "is_array" + }, + { + "field": "deployments.0.deploymentId", + "operation": "is_string" + }, + { + "field": "bundle.url", + "operation": "not_empty" + }, + { + "field": "deployments.0.url", + "operation": "not_empty" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-3.2", + "name": "Get Deployments With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json", + "If-None-Match": "{manifestEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.3", + "name": "Download Deployment Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.ETag", + "operation": "exists" + } + ], + "extract_context": { + "bundleEtag": "_headers.ETag" + } + }, + { + "id": "step-3.4", + "name": "Download Bundle With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "headers": { + "If-None-Match": "{bundleEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.5", + "name": "Download Individual Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "_headers.Content-Type", + "operation": "contains", + "value": "application/yaml" + }, + { + "field": "_headers.Cache-Control", + "operation": "contains", + "value": "immutable" + }, + { + "field": "_headers.Vary", + "operation": "contains", + "value": "Accept-Encoding" + }, + { + "field": "_headers.ETag", + "operation": "contains", + "value": "{deploymentDigest}" + } + ], + "extract_context": { + "deploymentEtag": "_headers.ETag" + } + }, + { + "id": "step-3.6", + "name": "Download Individual Deployment Manifest With Matching ETag", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "headers": { + "If-None-Match": "{deploymentEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {} + }, + { + "id": "step-3.7", + "name": "Report Deployment Status", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 200, + "validations": [ + { + "field": "acknowledgement", + "operation": "equals", + "value": "received" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-onboarding-errors", + "name": "Onboarding Error Handling", + "description": "Spec-shaped 400 and 401 onboarding responses.", + "steps": [ + { + "id": "step-4.1", + "name": "Reject Onboarding With Invalid Api Version", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "v1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "apiVersion" + } + ], + "extract_context": {} + }, + { + "id": "step-4.2", + "name": "Reject Onboarding With Missing Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest" + }, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.3", + "name": "Reject Onboarding With Empty Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "" + }, + "skip_certificate_injection": true, + "headers": { + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "certificate" + } + ], + "extract_context": {} + }, + { + "id": "step-4.5", + "name": "Reject Onboarding With Missing Kind", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.6", + "name": "Reject Onboarding With Wrong Kind Value", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "WrongKind", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "kind" + } + ], + "extract_context": {} + }, + { + "id": "step-4.4", + "name": "Onboard Without Signature Succeeds", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "is_string" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-capabilities-errors", + "name": "Capabilities Error Handling", + "description": "Negative tests for digest, schema, role, interface, and client validation.", + "steps": [ + { + "id": "step-5.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-5.1", + "name": "Reject Capabilities With Missing Properties", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest" + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.2", + "name": "Reject Capabilities With Invalid Role", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-002", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Unknown Role" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.3", + "name": "Reject Capabilities With Invalid Interface Type", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-003", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "serial" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.4", + "name": "Reject Capabilities With Invalid Cpu Architecture", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-004", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "sparc" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-5.5", + "name": "Reject Capabilities With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-005", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-5.6", + "name": "Reject Capabilities Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-006", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature verification failed" + } + ], + "extract_context": {} + }, + { + "id": "step-5.7", + "name": "Reject Capabilities For Unknown Client", + "method": "POST", + "endpoint": "/api/v1/clients/not-a-real-client/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-007", + "vendor": "Acme Corp", + "modelNumber": "ACM-XYZ", + "serialNumber": "SN-12345", + "roles": [ + "Standalone Device" + ], + "resources": { + "cpu": { + "cores": 4, + "architecture": "arm64" + }, + "memory": "16Gi", + "storage": "256Gi", + "interfaces": [ + { + "type": "ethernet" + } + ], + "peripherals": [] + } + } + }, + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Client not found" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-status-and-retrieval-errors", + "name": "Status And Retrieval Errors", + "description": "Negative coverage for deployment content negotiation, immutable resource lookup, and status schema validation.", + "steps": [ + { + "id": "step-6.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": { + }, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-6.1", + "name": "Get Current Deployments (Setup)", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { + "field": "deployments.0.deploymentId", + "operation": "exists" + } + ], + "extract_context": { + "manifestEtag": "_headers.ETag", + "bundleDigest": "bundle.digest", + "deploymentId": "deployments.0.deploymentId", + "deploymentDigest": "deployments.0.digest" + } + }, + { + "id": "step-6.2", + "name": "Reject Deployments Request With Unsupported Accept Header", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/json" + }, + "expected_status": 406, + "validations": [], + "extract_context": {} + }, + { + "id": "step-6.3", + "name": "Reject Bundle Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Bundle not found" + } + ], + "extract_context": {} + }, + { + "id": "step-6.4", + "name": "Reject Deployment Manifest Download With Wrong Digest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/not-the-right-digest", + "headers": { + }, + "expected_status": 404, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Deployment not found for digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.5", + "name": "Reject Status With Invalid State", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "done" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.6", + "name": "Reject Status With Missing Component Name", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.7", + "name": "Reject Status With Path Deployment Mismatch", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "another-deployment", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + }, + "expected_status": 422, + "validations": [ + { + "field": "errors", + "operation": "is_array" + } + ], + "extract_context": {} + }, + { + "id": "step-6.8", + "name": "Reject Status With Missing Content-Digest", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "headers": { + "Content-Digest": "" + }, + "expected_status": 400, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "content-digest" + } + ], + "extract_context": {} + }, + { + "id": "step-6.9", + "name": "Reject Status Without Signature", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { + "state": "installed" + }, + "components": [ + { + "name": "app-component-1", + "state": "installed" + } + ] + }, + "skip_signing": true, + "headers": { + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.10", + "name": "Reject Unsigned GET Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "skip_signing": true, + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.11", + "name": "Reject Unsigned GET Bundle", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/bundles/{bundleDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + }, + { + "id": "step-6.12", + "name": "Reject Unsigned GET Deployment Manifest", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/{deploymentDigest}", + "skip_signing": true, + "headers": {}, + "expected_status": 401, + "validations": [ + { + "field": "error", + "operation": "contains", + "value": "Signature" + } + ], + "extract_context": {} + } + ] + }, + { + "id": "scenario-live-assertion-demo", + "name": "Live Assertion Demo — Dynamic Error Code", + "description": "DEMO SCENARIO: Proves server reloads assertions.json on every restart. Step 7.1 sends an invalid capabilities request (missing apiVersion) which triggers a validation error. The expected HTTP status code comes directly from error_responses.unprocessable.status_code in assertions.json. Change that one value, restart, re-run — the code changes without touching any Go code.", + "steps": [ + { + "id": "step-7.0", + "name": "Onboard Device (Demo Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { + "field": "clientId", + "operation": "exists" + } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-7.1", + "name": "Invalid Capabilities (missing apiVersion) — expects 422 from assertion", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "demo-device-001", + "vendor": "Demo Corp", + "modelNumber": "DEMO-X1", + "serialNumber": "SN-DEMO-001", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "amd64" }, + "memory": "8Gi", + "storage": "128Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 422, + "validations": [ + { + "field": "status", + "operation": "exists" + } + ], + "extract_context": {} + } + ] + } + +] diff --git a/Data-Generator/margo-test-gen.sh b/Data-Generator/margo-test-gen.sh new file mode 100755 index 0000000..4a8408d --- /dev/null +++ b/Data-Generator/margo-test-gen.sh @@ -0,0 +1,207 @@ +#!/usr/bin/env bash + +################################################################################ +# MARGO Test Case Generator - Data-Generator CLI +################################################################################ +# Purpose: Generate and prepare test cases for MARGO personas +# Personas: WFM Supplier, Device Supplier +# +# For WFM Supplier: Uses Portman to generate postman_collection.json from OpenAPI +# For Device Supplier: References existing test-scenarios.json with assertions +################################################################################ + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFORMANCE_DIR="$(cd "$ROOT_DIR/.." && pwd)" +WFM_DIR="$CONFORMANCE_DIR/wfm-supplier" +DEVICE_DIR="$CONFORMANCE_DIR/device-supplier" +DATA_GEN_DIR="$ROOT_DIR" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# ============================================ +# Utility Functions +# ============================================ +log() { + echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*" +} + +success() { + echo -e "${GREEN}✅ $*${NC}" +} + +error() { + echo -e "${RED}❌ $*${NC}" + exit 1 +} + +warning() { + echo -e "${YELLOW}⚠️ $*${NC}" +} + +# ============================================ +# WFM Supplier - Generate test cases via Portman +# ============================================ +wfm_generate() { + local base_url="${1:-}" + + if [[ -z "$base_url" ]]; then + read -p "Enter WFM Base URL (e.g., https://symphony.machine:8082/v1alpha2/margo): " base_url + fi + + if [[ -z "$base_url" ]]; then + error "WFM Base URL is required" + fi + + log "🔄 Generating test cases for WFM Supplier from OpenAPI spec..." + + # Ensure output directory exists + mkdir -p "$DATA_GEN_DIR/wfm-supplier" + + # Run Portman to generate postman collection from OpenAPI + (cd "$WFM_DIR" && bash 1-setup_portman.sh "$base_url") || error "Portman generation failed" + + # Copy generated postman_collection.json to Data-Generator directory + if [[ -f "$WFM_DIR/postman_collection.json" ]]; then + cp "$WFM_DIR/postman_collection.json" "$DATA_GEN_DIR/wfm-supplier/" + success "WFM test cases generated: $DATA_GEN_DIR/wfm-supplier/postman_collection.json" + else + error "postman_collection.json not found after Portman generation" + fi + + # Also copy iteration/data files if they exist + if [[ -d "$WFM_DIR/newman-data" ]]; then + cp -r "$WFM_DIR/newman-data" "$DATA_GEN_DIR/wfm-supplier/" 2>/dev/null || true + success "Newman data files copied" + fi +} + +# ============================================ +# Device Supplier - Reference existing test scenarios +# ============================================ +device_generate() { + log "📋 Preparing Device Supplier test scenarios..." + + # Ensure output directory exists + mkdir -p "$DATA_GEN_DIR/device-supplier" + + # Device supplier uses pre-existing test scenarios + if [[ -f "$DEVICE_DIR/device-scenarios/test-scenarios.json" ]]; then + cp "$DEVICE_DIR/device-scenarios/test-scenarios.json" "$DATA_GEN_DIR/device-supplier/" + success "Device test scenarios ready: $DATA_GEN_DIR/device-supplier/test-scenarios.json" + else + error "test-scenarios.json not found in device-supplier" + fi + + # Copy data files + if [[ -d "$DEVICE_DIR/data" ]]; then + cp -r "$DEVICE_DIR/data" "$DATA_GEN_DIR/device-supplier/" 2>/dev/null || true + success "Device data files copied" + fi +} + +# ============================================ +# Show usage +# ============================================ +usage() { + cat <<'EOF' +MARGO Test Case Generator (Data-Generator CLI) + +Usage: + ./margo-test-gen.sh [PERSONA] [OPTIONS] + +Personas: + 1, wfm Generate WFM Supplier test cases via Portman + 2, device Prepare Device Supplier test scenarios + interactive Interactive menu (default) + +Examples: + ./margo-test-gen.sh wfm https://symphony.machine:8082/v1alpha2/margo + ./margo-test-gen.sh device + ./margo-test-gen.sh interactive + ./margo-test-gen.sh (runs interactive mode) + +Output Locations: + WFM: ./Data-Generator/wfm-supplier/postman_collection.json + Device: ./Data-Generator/device-supplier/test-scenarios.json + +EOF +} + +# ============================================ +# Interactive Menu +# ============================================ +interactive_menu() { + while true; do + clear + echo "======================================================================" + echo " MARGO Test Case Generator (Data-Generator)" + echo "======================================================================" + echo "" + echo "Select Persona:" + echo " 1. WFM Supplier - Generate test cases from OpenAPI spec" + echo " 2. Device Supplier - Prepare test scenarios" + echo " 3. Exit" + echo "" + read -p "Enter choice (1-3): " choice + + case "$choice" in + 1|wfm) + read -p "Enter WFM Base URL (default: https://symphony.machine:8082/v1alpha2/margo): " url + wfm_generate "${url:-https://symphony.machine:8082/v1alpha2/margo}" + read -p "Press Enter to continue..." _ + ;; + 2|device) + device_generate + read -p "Press Enter to continue..." _ + ;; + 3|exit) + log "Exiting..." + exit 0 + ;; + *) + error "Invalid choice" + ;; + esac + done +} + +# ============================================ +# Main +# ============================================ +main() { + local persona="${1:-}" + local arg1="${2:-}" + + # Interactive mode if no arguments + if [[ -z "$persona" ]]; then + interactive_menu + return 0 + fi + + case "$persona" in + 1|wfm) + wfm_generate "$arg1" + ;; + 2|device) + device_generate + ;; + interactive) + interactive_menu + ;; + help|--help|-h) + usage + ;; + *) + error "Unknown persona: $persona" + ;; + esac +} + +main "$@" diff --git a/Data-Generator/wfm-supplier/.functional-tests b/Data-Generator/wfm-supplier/.functional-tests new file mode 100644 index 0000000..e69de29 diff --git a/Data-Generator/wfm-supplier/groups/bronze grp/group.json b/Data-Generator/wfm-supplier/groups/bronze grp/group.json new file mode 100644 index 0000000..2d1570c --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/bronze grp/group.json @@ -0,0 +1,57 @@ +{ + "name": "bronze grp", + "version": "1.1.2", + "persona": "wfm-supplier", + "description": "using bronze grp", + "FolderPath": [ + "Data-Generator/wfm-supplier/groups/bronze grp", + "testcases/user1-wfm" + ], + "testCases": [ + "02555be8-873a-4f60-b961-449291382227", + "0510e725-a124-415f-a9b9-0d369e1d94e2", + "066c0155-a489-428e-9535-dabb36c7aaf6", + "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "0dd06053-e16c-419a-a533-f8cddb42471a", + "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "215cf5ba-da42-4358-bc8f-daae289826cd", + "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "5755e4a7-8329-4ceb-b210-8c41e6423569", + "586381df-bdc6-4b0f-8a1b-3316641b5317", + "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "6babf73f-f617-4f25-a1b6-414b665ed6b5", + "6e674338-64ef-434c-9905-3ddff3d14877", + "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "7b600483-4a8d-41ea-957c-88600e2a5f83", + "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "80315591-d033-4c57-8d63-9979889e6317", + "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "a7d2c754-66c3-4e45-aecb-987e481d9343", + "a99303f4-742b-494a-a822-31265b7f8443", + "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "aee967e3-204c-4193-b500-2559110e5c02", + "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "dc7a02ba-be8f-4a50-a95d-084a02839652", + "e0358da8-3b31-4278-af5f-84d5e347bacd", + "e89bca4b-f257-434a-8397-d604c2b42eb8", + "eb9e178c-5df0-420c-8169-c223cc174a86", + "f206fb46-f592-45ea-a6f1-6569371ee515", + "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "fc6a5159-3b3f-4140-8092-25992e18f959" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/bronze grp/postman_collection.json b/Data-Generator/wfm-supplier/groups/bronze grp/postman_collection.json new file mode 100644 index 0000000..e8584c8 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/bronze grp/postman_collection.json @@ -0,0 +1,2395 @@ +{ + "_": { + "postman_id": "6babf73f-f617-4f25-a1b6-414b665ed6b5" + }, + "item": [ + { + "id": "dc7a02ba-be8f-4a50-a95d-084a02839652", + "name": "Download Root CA certificate", + "request": { + "name": "Download Root CA certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "GET", + "body": {} + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "name": "Root CA certificate", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"certificate\": \"eiusmod\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "fc6a5159-3b3f-4140-8092-25992e18f959", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/onboarding/certificate - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/onboarding/certificate - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/onboarding/certificate - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"properties\":{\"certificate\":{\"type\":\"string\",\"description\":\"Base64-encoded certificate text\"}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/onboarding/certificate - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "0dd06053-e16c-419a-a533-f8cddb42471a", + "name": "Complete onboarding with client certificate", + "request": { + "name": "Complete onboarding with client certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "name": "New client onboarded successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"clientId\": \"enim deserunt\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "name": "Invalid certificate format or structure.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Invalid certificate\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "e89bca4b-f257-434a-8397-d604c2b42eb8", + "name": "Client certificate not trusted or client rejected.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Client rejected\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/onboarding - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[POST]::/api/v1/onboarding - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[POST]::/api/v1/onboarding - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"properties\":{\"clientId\":{\"type\":\"string\"}},\"type\":\"object\"}\n\n// Validate if response matches JSON schema \npm.test(\"[POST]::/api/v1/onboarding - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "name": "Report device capabilities", + "request": { + "name": "Report device capabilities", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "0510e725-a124-415f-a9b9-0d369e1d94e2", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f206fb46-f592-45ea-a6f1-6569371ee515", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "066c0155-a489-428e-9535-dabb36c7aaf6", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "a99303f4-742b-494a-a822-31265b7f8443", + "name": "Update device capabilities (Update)", + "request": { + "name": "Update device capabilities (Update)", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "eb9e178c-5df0-420c-8169-c223cc174a86", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "7b600483-4a8d-41ea-957c-88600e2a5f83", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "586381df-bdc6-4b0f-8a1b-3316641b5317", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[PUT]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "name": "Retrieve bundle information for a specific device and digest", + "request": { + "name": "Retrieve bundle information for a specific device and digest", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the device-client", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "name": "Bundle archive (immutable)", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "aute magna" + } + ], + "body": "ut nostrud", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "5755e4a7-8329-4ceb-b210-8c41e6423569", + "name": "Representation not modified", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "a7d2c754-66c3-4e45-aecb-987e481d9343", + "name": "Invalid request.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "80315591-d033-4c57-8d63-9979889e6317", + "name": "Bundle not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Content-Type is application/vnd.margo.bundle.v1+tar+gzip\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.bundle.v1+tar+gzip\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "215cf5ba-da42-4358-bc8f-daae289826cd", + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "request": { + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) The unique identifier of the Edge Compute Device making the request", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "name": "Manifest returned in the negotiated format", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "disabled": true, + "description": { + "content": "Format of the returned manifest", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + } + ], + "body": "{\n \"manifestVersion\": -83824536.23767403,\n \"bundle\": {\n \"mediaType\": \"Lorem\",\n \"digest\": \"non i\",\n \"sizeBytes\": -77785071.88778825,\n \"url\": \"ad exercitation sint cupidatat\"\n },\n \"deployments\": [\n {\n \"deploymentId\": \"culpa\",\n \"digest\": \"eiusmod\",\n \"url\": \"sed occaecat\",\n \"sizeBytes\": 37257419.806667894\n },\n {\n \"deploymentId\": \"Duis occaecat\",\n \"digest\": \"ad irure\",\n \"url\": \"in\",\n \"sizeBytes\": -51875188.13968461\n }\n ],\n \"bundle.mediaType\": false,\n \"bundle.digest\": false,\n \"bundle.url\": false\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "name": "Not Modified - Manifest has not changed", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "name": "Not Acceptable - Server cannot generate a response matching the Accept header", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Acceptable", + "code": 406, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Content-Type is application/vnd.margo.manifest.v1+json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.manifest.v1+json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"required\":[\"manifestVersion\",\"bundle\",\"bundle.mediaType\",\"bundle.digest\",\"bundle.url\",\"deployments\"],\"properties\":{\"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.\\n\"},\"bundle\":{\"type\":[\"object\",\"null\"],\"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).\\n\",\"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.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable retrieval endpoint of the form /api/v1/clients/{clientId}/bundles/{digest} where {digest} equals bundle.digest.\\n\"}}},\"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\":{\"type\":\"object\",\"description\":\"Reference to a deployment manifest with content addressing and integrity verification.\\n\",\"required\":[\"deploymentId\",\"digest\",\"url\"],\"properties\":{\"deploymentId\":{\"type\":\"string\",\"description\":\"The unique UUID from the ApplicationDeployment's metadata.annotations.id.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable endpoint of the form /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}. The {digest} MUST equal deployments[].digest; the referenced resource is immutable\\n\"}}}}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "name": "Retrieve an individual ApplicationDeployment YAML file", + "request": { + "name": "Retrieve an individual ApplicationDeployment YAML file", + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the Edge Compute Device", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) UUID of the ApplicationDeployment (metadata.annotations.id)", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "deploymentId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.\n", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/yaml" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "name": "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.\n", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/yaml" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/yaml" + }, + { + "disabled": true, + "description": { + "content": "application/yaml", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Accept-Encoding", + "type": "text/plain" + }, + "key": "Vary", + "value": "aute magna" + } + ], + "body": "officia dolor", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "e0358da8-3b31-4278-af5f-84d5e347bacd", + "name": "Deployment not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Content-Type is application/yaml\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/yaml\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "name": "Report deployment status", + "request": { + "name": "Report deployment status", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "deploymentId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "name": "The deployment status was added, or updated, successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "OK", + "code": 200, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "aee967e3-204c-4193-b500-2559110e5c02", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6e674338-64ef-434c-9905-3ddff3d14877", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "02555be8-873a-4f60-b961-449291382227", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/deployments/:deploymentId/status - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + } + ], + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + }, + "event": [], + "variable": [ + { + "type": "any", + "value": "https://wfm.margo.org/", + "key": "baseUrl" + } + ], + "info": { + "_postman_id": "6babf73f-f617-4f25-a1b6-414b665ed6b5", + "name": "Margo Workload Management API", + "version": { + "raw": "1.0.0", + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": [], + "build": [], + "string": "1.0.0" + }, + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": { + "content": "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.", + "type": "text/plain" + } + } +} \ No newline at end of file diff --git a/Data-Generator/wfm-supplier/groups/core/group.json b/Data-Generator/wfm-supplier/groups/core/group.json new file mode 100644 index 0000000..0686327 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/core/group.json @@ -0,0 +1,11 @@ +{ + "name": "core", + "version": "1.0.0-rc.2", + "persona": "wfm-supplier", + "description": "Generic/positive/negative/edge coverage of WFM Supplier conformance requirements not exercised by the other groups: device-role capability variants (Standalone Cluster vs Standalone Device), invalid supportedDeploymentTypes/supportedRuntimes enum values, and default content negotiation when Accept is omitted. Declarative scenario format (not Postman) — proves out the same self-service authoring model device-supplier already uses.", + "FolderPath": [ + "testcases/wfm-core" + ], + "flexibleOrder": false, + "testCases": [] +} diff --git a/Data-Generator/wfm-supplier/groups/diamond/group.json b/Data-Generator/wfm-supplier/groups/diamond/group.json new file mode 100644 index 0000000..48b61e0 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/diamond/group.json @@ -0,0 +1,102 @@ +{ + "name": "diamond", + "version": "1.0.0", + "persona": "wfm-supplier", + "description": "v1.0.0", + "FolderPath": [ + "testcases/user1", + "testcases/user2" + ], + "testCases": [ + "02555be8-873a-4f60-b961-449291382227", + "045403b4-89ac-4c08-9146-7a92040c3476", + "04562ab9-d47a-47c9-81c5-03301acae6bd", + "0510e725-a124-415f-a9b9-0d369e1d94e2", + "066c0155-a489-428e-9535-dabb36c7aaf6", + "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "0b4b5451-41c9-4155-9724-e1a8fe863ca0", + "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "0dd06053-e16c-419a-a533-f8cddb42471a", + "10811a89-c9bf-4b22-9e7e-9a34eb45a054", + "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "1a5d47ce-5f1a-4f7a-ad56-061e87183fa6", + "1f66d6e9-4a85-4ceb-a693-f1a43e5ca2c8", + "1ff8dae9-06d3-486e-b156-5e2cd80e7a56", + "215cf5ba-da42-4358-bc8f-daae289826cd", + "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "2dea28c5-00e4-4cab-b6e2-d199cea1cfe4", + "342e096c-893c-4f76-b6d6-f0bbb1c2066f", + "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "387af239-f4e4-429b-9584-90c414e0a7c4", + "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "3e26c5c6-ae6e-4abb-9012-84cb05939f62", + "462ffe48-2af8-46c2-9781-ccbfa0860d0c", + "469d2b44-34c0-4bba-ad20-4c7259c22031", + "4934b7a1-d099-4702-afb6-9bb4681b4713", + "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "55b7012f-aa47-4c20-903d-79c301ab8de9", + "5755e4a7-8329-4ceb-b210-8c41e6423569", + "586381df-bdc6-4b0f-8a1b-3316641b5317", + "5f847811-b779-4c72-ab6d-8e583b3950ac", + "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "5ffd6386-9b89-4bb4-8f4d-2ed8b85a381f", + "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "6a805ce8-58f8-4845-81f6-fa3322bd8f9b", + "6e674338-64ef-434c-9905-3ddff3d14877", + "6ec4dc6e-ea73-4528-85e7-7880e7e9e816", + "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "7392e234-6f45-43e2-a027-b0a86bad517e", + "7b600483-4a8d-41ea-957c-88600e2a5f83", + "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "7ccf9c54-36ea-42e2-b4fe-f6e00910c944", + "7e655ed3-f370-463d-b506-630fb0defdbf", + "80315591-d033-4c57-8d63-9979889e6317", + "83aa0550-a4aa-451b-be6f-37600ab6a414", + "87d8faa5-25fe-442b-bda0-2fc0ddf983b6", + "8ab3b05f-46c4-4c50-8104-8982f060f1ce", + "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "8d5d19ed-a5c2-4216-8fd1-c50b05aadefe", + "8df9329e-5177-4d12-b05c-2bc81d63a76a", + "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "92d987db-beaa-467c-97dd-059c18556681", + "98f57b60-ffd9-4832-a944-0db7ce1ecede", + "9bed5895-ee56-417f-96c8-5d2fd3c7dd2d", + "a04696b2-7bff-4460-8d8d-b992f193b4db", + "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "a5efd1c1-9806-4aac-9901-5d87b45424c1", + "a7d2c754-66c3-4e45-aecb-987e481d9343", + "a99303f4-742b-494a-a822-31265b7f8443", + "aa4cfb2b-3d00-420b-a479-0c8ce289f2ec", + "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "aee967e3-204c-4193-b500-2559110e5c02", + "b560e49d-169f-40f7-b1ec-07620a7620a9", + "c006a5d9-d966-4b2c-b21f-e02a03bf5be5", + "c02c5cde-8707-45d1-b5b5-fb9238efb3ac", + "c2706fbd-e147-4a78-a04b-79c86c46387c", + "c37cb9e4-24a5-4106-bbbb-a48feaf4bee1", + "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "ca621765-37e6-44b8-b846-9635b37bb1ba", + "cc86f6b1-287a-4e63-bbaa-147e162fb23f", + "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "d3cae471-6d2e-4ef0-9569-6152f8d722ff", + "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "dc7a02ba-be8f-4a50-a95d-084a02839652", + "e0358da8-3b31-4278-af5f-84d5e347bacd", + "e71e3fb8-62a3-4e2b-9511-0f8a3b52083e", + "e89bca4b-f257-434a-8397-d604c2b42eb8", + "eb9e178c-5df0-420c-8169-c223cc174a86", + "ed4a34b9-7c61-4289-885e-5b37cc02b01e", + "f206fb46-f592-45ea-a6f1-6569371ee515", + "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "f5bc7d9f-965f-4c6b-a4cb-398b3c1aff78", + "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "fc6a5159-3b3f-4140-8092-25992e18f959", + "6babf73f-f617-4f25-a1b6-414b665ed6b5", + "ca81b225-fab5-44b0-97d3-82588fc250e2" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/seimens/group.json b/Data-Generator/wfm-supplier/groups/seimens/group.json new file mode 100644 index 0000000..bd5bcd2 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/seimens/group.json @@ -0,0 +1,56 @@ +{ + "name": "seimens", + "version": "v1.0.0", + "persona": "wfm-supplier", + "description": "v1.0.0", + "FolderPath": [ + "testcases/user1" + ], + "testCases": [ + "02555be8-873a-4f60-b961-449291382227", + "0510e725-a124-415f-a9b9-0d369e1d94e2", + "066c0155-a489-428e-9535-dabb36c7aaf6", + "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "0dd06053-e16c-419a-a533-f8cddb42471a", + "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "215cf5ba-da42-4358-bc8f-daae289826cd", + "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "5755e4a7-8329-4ceb-b210-8c41e6423569", + "586381df-bdc6-4b0f-8a1b-3316641b5317", + "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "6e674338-64ef-434c-9905-3ddff3d14877", + "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "7b600483-4a8d-41ea-957c-88600e2a5f83", + "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "80315591-d033-4c57-8d63-9979889e6317", + "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "a7d2c754-66c3-4e45-aecb-987e481d9343", + "a99303f4-742b-494a-a822-31265b7f8443", + "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "aee967e3-204c-4193-b500-2559110e5c02", + "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "dc7a02ba-be8f-4a50-a95d-084a02839652", + "e0358da8-3b31-4278-af5f-84d5e347bacd", + "e89bca4b-f257-434a-8397-d604c2b42eb8", + "eb9e178c-5df0-420c-8169-c223cc174a86", + "f206fb46-f592-45ea-a6f1-6569371ee515", + "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "fc6a5159-3b3f-4140-8092-25992e18f959", + "6babf73f-f617-4f25-a1b6-414b665ed6b5" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/silver/group.json b/Data-Generator/wfm-supplier/groups/silver/group.json new file mode 100644 index 0000000..e6735f3 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/silver/group.json @@ -0,0 +1,105 @@ +{ + "name": "silver", + "version": "1.0.0-rc.2", + "persona": "wfm-supplier", + "description": "Regenerated via CLI-1 (E2E verification pass)", + "FolderPath": [ + "Data-Generator/wfm-supplier/groups/silver", + "testcases/user1", + "testcases/user2" + ], + "flexibleOrder": false, + "testCases": [ + "02555be8-873a-4f60-b961-449291382227", + "045403b4-89ac-4c08-9146-7a92040c3476", + "04562ab9-d47a-47c9-81c5-03301acae6bd", + "0510e725-a124-415f-a9b9-0d369e1d94e2", + "066c0155-a489-428e-9535-dabb36c7aaf6", + "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "0b4b5451-41c9-4155-9724-e1a8fe863ca0", + "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "0dd06053-e16c-419a-a533-f8cddb42471a", + "10811a89-c9bf-4b22-9e7e-9a34eb45a054", + "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "1a5d47ce-5f1a-4f7a-ad56-061e87183fa6", + "1f66d6e9-4a85-4ceb-a693-f1a43e5ca2c8", + "1ff8dae9-06d3-486e-b156-5e2cd80e7a56", + "215cf5ba-da42-4358-bc8f-daae289826cd", + "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "2dea28c5-00e4-4cab-b6e2-d199cea1cfe4", + "342e096c-893c-4f76-b6d6-f0bbb1c2066f", + "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "387af239-f4e4-429b-9584-90c414e0a7c4", + "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "3e26c5c6-ae6e-4abb-9012-84cb05939f62", + "462ffe48-2af8-46c2-9781-ccbfa0860d0c", + "469d2b44-34c0-4bba-ad20-4c7259c22031", + "4934b7a1-d099-4702-afb6-9bb4681b4713", + "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "55b7012f-aa47-4c20-903d-79c301ab8de9", + "5755e4a7-8329-4ceb-b210-8c41e6423569", + "586381df-bdc6-4b0f-8a1b-3316641b5317", + "5f847811-b779-4c72-ab6d-8e583b3950ac", + "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "5ffd6386-9b89-4bb4-8f4d-2ed8b85a381f", + "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "6a805ce8-58f8-4845-81f6-fa3322bd8f9b", + "6babf73f-f617-4f25-a1b6-414b665ed6b5", + "6e674338-64ef-434c-9905-3ddff3d14877", + "6ec4dc6e-ea73-4528-85e7-7880e7e9e816", + "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "7392e234-6f45-43e2-a027-b0a86bad517e", + "7b600483-4a8d-41ea-957c-88600e2a5f83", + "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "7ccf9c54-36ea-42e2-b4fe-f6e00910c944", + "7e655ed3-f370-463d-b506-630fb0defdbf", + "80315591-d033-4c57-8d63-9979889e6317", + "83aa0550-a4aa-451b-be6f-37600ab6a414", + "87d8faa5-25fe-442b-bda0-2fc0ddf983b6", + "8ab3b05f-46c4-4c50-8104-8982f060f1ce", + "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "8d5d19ed-a5c2-4216-8fd1-c50b05aadefe", + "8df9329e-5177-4d12-b05c-2bc81d63a76a", + "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "92d987db-beaa-467c-97dd-059c18556681", + "98f57b60-ffd9-4832-a944-0db7ce1ecede", + "9bed5895-ee56-417f-96c8-5d2fd3c7dd2d", + "a04696b2-7bff-4460-8d8d-b992f193b4db", + "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "a5efd1c1-9806-4aac-9901-5d87b45424c1", + "a7d2c754-66c3-4e45-aecb-987e481d9343", + "a99303f4-742b-494a-a822-31265b7f8443", + "aa4cfb2b-3d00-420b-a479-0c8ce289f2ec", + "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "aee967e3-204c-4193-b500-2559110e5c02", + "b560e49d-169f-40f7-b1ec-07620a7620a9", + "c006a5d9-d966-4b2c-b21f-e02a03bf5be5", + "c02c5cde-8707-45d1-b5b5-fb9238efb3ac", + "c2706fbd-e147-4a78-a04b-79c86c46387c", + "c37cb9e4-24a5-4106-bbbb-a48feaf4bee1", + "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "ca621765-37e6-44b8-b846-9635b37bb1ba", + "ca81b225-fab5-44b0-97d3-82588fc250e2", + "cc86f6b1-287a-4e63-bbaa-147e162fb23f", + "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "d3cae471-6d2e-4ef0-9569-6152f8d722ff", + "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "dc7a02ba-be8f-4a50-a95d-084a02839652", + "e0358da8-3b31-4278-af5f-84d5e347bacd", + "e71e3fb8-62a3-4e2b-9511-0f8a3b52083e", + "e89bca4b-f257-434a-8397-d604c2b42eb8", + "eb9e178c-5df0-420c-8169-c223cc174a86", + "ed4a34b9-7c61-4289-885e-5b37cc02b01e", + "f206fb46-f592-45ea-a6f1-6569371ee515", + "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "f5bc7d9f-965f-4c6b-a4cb-398b3c1aff78", + "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "fc6a5159-3b3f-4140-8092-25992e18f959", + "silver" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/silver/postman_collection.json b/Data-Generator/wfm-supplier/groups/silver/postman_collection.json new file mode 100644 index 0000000..ced2a26 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/silver/postman_collection.json @@ -0,0 +1,2417 @@ +{ + "_": { + "postman_id": "6babf73f-f617-4f25-a1b6-414b665ed6b5" + }, + "item": [ + { + "id": "dc7a02ba-be8f-4a50-a95d-084a02839652", + "name": "Download Root CA certificate", + "request": { + "name": "Download Root CA certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "GET", + "body": {} + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "c42f4b7d-992a-4af0-924b-2eb4d787678a", + "name": "Root CA certificate", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"certificate\": \"eiusmod\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "fc6a5159-3b3f-4140-8092-25992e18f959", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/onboarding/certificate - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/onboarding/certificate - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/onboarding/certificate - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"properties\":{\"certificate\":{\"type\":\"string\",\"description\":\"Base64-encoded certificate text\"}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/onboarding/certificate - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "0dd06053-e16c-419a-a533-f8cddb42471a", + "name": "Complete onboarding with client certificate", + "request": { + "name": "Complete onboarding with client certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "0b95ee4e-dc64-4119-b07e-69c3342da26a", + "name": "New client onboarded successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"clientId\": \"enim deserunt\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "f9e10c20-8474-47ec-81c0-fc7c0823891d", + "name": "Invalid certificate format or structure.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Invalid certificate\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "e89bca4b-f257-434a-8397-d604c2b42eb8", + "name": "Client certificate not trusted or client rejected.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur elit eu veniam\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"veniam\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Client rejected\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "d05053ea-7ea1-4199-ad89-e629b3cde65c", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/onboarding - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[POST]::/api/v1/onboarding - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[POST]::/api/v1/onboarding - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"properties\":{\"clientId\":{\"type\":\"string\"}},\"type\":\"object\"}\n\n// Validate if response matches JSON schema \npm.test(\"[POST]::/api/v1/onboarding - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "165f8444-a0e2-4ef1-8bbb-58295b3e02a2", + "name": "Report device capabilities", + "request": { + "name": "Report device capabilities", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "type": "any", + "value": "", + "key": "deviceId", + "description": { + "content": "(Required) ", + "type": "text/plain" + } + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "0510e725-a124-415f-a9b9-0d369e1d94e2", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f206fb46-f592-45ea-a6f1-6569371ee515", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "5fc47546-2c1a-4956-9b6a-cfdfb31b88f6", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "066c0155-a489-428e-9535-dabb36c7aaf6", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "a3f7146c-5c7f-41f1-82d4-9ed75c84ec24", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "4caa7c0d-a601-4a36-93ed-7d4a7d774f46", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "a99303f4-742b-494a-a822-31265b7f8443", + "name": "Update device capabilities (Update)", + "request": { + "name": "Update device capabilities (Update)", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "type": "any", + "value": "", + "key": "deviceId", + "description": { + "content": "(Required) ", + "type": "text/plain" + } + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "8bb41ecf-4010-4dd0-ba9e-11033cfe66cd", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "eb9e178c-5df0-420c-8169-c223cc174a86", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "7b600483-4a8d-41ea-957c-88600e2a5f83", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6fb8f5bb-2932-4287-adb3-4e2f0b477a90", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "8ec05b96-3f1d-4030-b2c6-67c9e98bf811", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"pariatur laborum officia eu\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"ea magna eu elit\",\n \"vendor\": \"esse in sed ullamco\",\n \"modelNumber\": \"occaecat u\",\n \"serialNumber\": \"ullamco magna incididunt\",\n \"roles\": [\n \"Standalone Device\",\n \"Cluster Leader\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 32691186.870693564,\n \"architecture\": \"amd64\"\n },\n \"memory\": \"laboris pariatur\",\n \"storage\": \"id\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"Excepteur labore sit\",\n \"model\": \"cupidata\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"nisi minim\",\n \"model\": \"do\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"wifi\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "586381df-bdc6-4b0f-8a1b-3316641b5317", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[PUT]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "7bcc0bad-9d1c-4514-8243-be92aafcf609", + "name": "Retrieve bundle information for a specific device and digest", + "request": { + "name": "Retrieve bundle information for a specific device and digest", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the device-client", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "195c5f23-c8c7-491a-b622-3ce29a0aa9c4", + "name": "Bundle archive (immutable)", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "aute magna" + } + ], + "body": "ut nostrud", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "5755e4a7-8329-4ceb-b210-8c41e6423569", + "name": "Representation not modified", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "a7d2c754-66c3-4e45-aecb-987e481d9343", + "name": "Invalid request.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "80315591-d033-4c57-8d63-9979889e6317", + "name": "Bundle not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "ad5f8b04-e05e-4153-99d6-a74773d6c565", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Content-Type is application/vnd.margo.bundle.v1+tar+gzip\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.bundle.v1+tar+gzip\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "215cf5ba-da42-4358-bc8f-daae289826cd", + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "request": { + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) The unique identifier of the Edge Compute Device making the request", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "2bd8b6a4-ac94-435b-a365-42f07a064bc3", + "name": "Manifest returned in the negotiated format", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "disabled": true, + "description": { + "content": "Format of the returned manifest", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + } + ], + "body": "{\n \"manifestVersion\": -83824536.23767403,\n \"bundle\": {\n \"mediaType\": \"Lorem\",\n \"digest\": \"non i\",\n \"sizeBytes\": -77785071.88778825,\n \"url\": \"ad exercitation sint cupidatat\"\n },\n \"deployments\": [\n {\n \"deploymentId\": \"culpa\",\n \"digest\": \"eiusmod\",\n \"url\": \"sed occaecat\",\n \"sizeBytes\": 37257419.806667894\n },\n {\n \"deploymentId\": \"Duis occaecat\",\n \"digest\": \"ad irure\",\n \"url\": \"in\",\n \"sizeBytes\": -51875188.13968461\n }\n ],\n \"bundle.mediaType\": false,\n \"bundle.digest\": false,\n \"bundle.url\": false\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "17a2b787-ca67-4dd6-a72b-27cd1290bebc", + "name": "Not Modified - Manifest has not changed", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f54748a1-72c1-4fb9-a64f-7e4b2b36ba54", + "name": "Not Acceptable - Server cannot generate a response matching the Accept header", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Acceptable", + "code": 406, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "0b19a87e-55aa-4f0c-91b0-c9ddfb0511dc", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Content-Type is application/vnd.margo.manifest.v1+json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.manifest.v1+json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"required\":[\"manifestVersion\",\"bundle\",\"bundle.mediaType\",\"bundle.digest\",\"bundle.url\",\"deployments\"],\"properties\":{\"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.\\n\"},\"bundle\":{\"type\":[\"object\",\"null\"],\"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).\\n\",\"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.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable retrieval endpoint of the form /api/v1/clients/{clientId}/bundles/{digest} where {digest} equals bundle.digest.\\n\"}}},\"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\":{\"type\":\"object\",\"description\":\"Reference to a deployment manifest with content addressing and integrity verification.\\n\",\"required\":[\"deploymentId\",\"digest\",\"url\"],\"properties\":{\"deploymentId\":{\"type\":\"string\",\"description\":\"The unique UUID from the ApplicationDeployment's metadata.annotations.id.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable endpoint of the form /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}. The {digest} MUST equal deployments[].digest; the referenced resource is immutable\\n\"}}}}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "d772612f-ef4c-48ab-bb98-5cc30eb30465", + "name": "Retrieve an individual ApplicationDeployment YAML file", + "request": { + "name": "Retrieve an individual ApplicationDeployment YAML file", + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the Edge Compute Device", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) UUID of the ApplicationDeployment (metadata.annotations.id)", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "deploymentId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.\n", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/yaml" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "36fdd629-6c79-4991-86a2-49be8dbcf96f", + "name": "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.\n", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "key": "Accept", + "value": "application/yaml" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/yaml" + }, + { + "disabled": true, + "description": { + "content": "application/yaml", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "ETag", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Accept-Encoding", + "type": "text/plain" + }, + "key": "Vary", + "value": "aute magna" + } + ], + "body": "officia dolor", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "e0358da8-3b31-4278-af5f-84d5e347bacd", + "name": "Deployment not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "aute magna" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "aute magna" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "60f5d625-d7de-4c1c-9820-134aefea4c7d", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Content-Type is application/yaml\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/yaml\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "4fd5d28a-d4c1-434c-b00d-2b136be54402", + "name": "Report deployment status", + "request": { + "name": "Report deployment status", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "aute magna", + "key": "deploymentId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0", + "name": "The deployment status was added, or updated, successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "OK", + "code": 200, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "aee967e3-204c-4193-b500-2559110e5c02", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "387e5c5b-1a88-42a8-8c8d-e46e7aa20865", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "292d8e91-d376-4d2b-81d9-7c44cbc89ef3", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6e674338-64ef-434c-9905-3ddff3d14877", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"in veniam aliqua deserunt non\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"aute velit\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"consectetur cupidatat\",\n \"message\": \"sed velit do\"\n }\n },\n \"components\": [\n {\n \"name\": \"sint reprehe\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"anim aliqua\",\n \"message\": \"consequat esse Duis pariatur\"\n }\n },\n {\n \"name\": \"sed qui Duis repre\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"deserunt\",\n \"message\": \"qui enim Ut\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "02555be8-873a-4f60-b961-449291382227", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/deployments/:deploymentId/status - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + } + ], + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + }, + "event": [], + "variable": [ + { + "type": "any", + "value": "https://wfm.margo.org/", + "key": "baseUrl" + } + ], + "info": { + "_postman_id": "6babf73f-f617-4f25-a1b6-414b665ed6b5", + "name": "Margo Workload Management API", + "version": { + "raw": "1.0.0", + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": [], + "build": [], + "string": "1.0.0" + }, + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": { + "content": "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.", + "type": "text/plain" + } + } +} diff --git a/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/group.json b/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/group.json new file mode 100644 index 0000000..94e9941 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/group.json @@ -0,0 +1,28 @@ +{ + "name": "vendor-negative-scenarios", + "version": "1.1.1", + "persona": "wfm-supplier", + "description": "new grp v1.1.1", + "FolderPath": [ + "Data-Generator/wfm-supplier/groups/vendor-negative-scenarios" + ], + "testCases": [ + "5a670495-f35e-452f-b87a-d6d48d06cfeb", + "746cb090-c884-466b-9c15-a79a88fc012b", + "6698850c-51b4-4b49-bd43-e755a89b9d3b", + "704d3d46-145c-4a4d-8e45-a11098a92076", + "11083d25-7236-471d-8455-89d8c67f9d10", + "76dc6c15-c78c-4f1d-b9e6-b37055dec7f8", + "d6472975-6b22-46b8-83fe-d730929ec369", + "16a17a99-8569-408a-9820-02ea32ee5f4a", + "cce2e8d1-dde4-41b0-893d-6b988c353b91", + "d0dbc06c-3c2c-431e-80af-99ef5baccc1b", + "ac5ccdb9-ba6c-4cfd-af52-1afc19860899", + "dceb4304-b240-469a-8e42-2d97d2b3bfd6", + "2f0f025c-3bb5-4e9f-9557-83a52fdaa2c1", + "4090c79a-2989-4b13-8823-325b34071123", + "fd1f9cbf-b5ae-4562-9b11-a46cca8a9e2e", + "7ec7ce3c-1e7d-4ecf-8827-1a6c3151fd23", + "8609c565-57fc-4a43-8cd7-ef395860ddf8" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/postman_collection.json b/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/postman_collection.json new file mode 100644 index 0000000..96fa988 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/vendor-negative-scenarios/postman_collection.json @@ -0,0 +1,361 @@ +{ + "info": { + "_postman_id": "8609c565-57fc-4a43-8cd7-ef395860ddf8", + "name": "Margo WFM Supplier — Negative Conformance Tests", + "description": "Negative conformance tests for the WFM Supplier persona. Covers error scenarios: bad certificate format (400), certificate not trusted (403), missing/invalid signature (400/401), wrong Accept header (406/500), semantic body errors (422), and unknown client (404). The runner automatically triggers each error by applying the appropriate strategy based on the response example code and name.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "id": "5a670495-f35e-452f-b87a-d6d48d06cfeb", + "name": "POST Onboarding — Invalid certificate format or structure", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "onboarding"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"onboarding.margo.org/v1alpha1\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"NOT_A_VALID_PEM_CERTIFICATE\"\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "746cb090-c884-466b-9c15-a79a88fc012b", + "name": "Invalid certificate format or structure.", + "code": 400, + "status": "Bad Request", + "header": [], + "body": "{\"error\": \"Invalid certificate format\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::/api/v1/onboarding - Invalid cert format returns 400 (or 401 if signature checked first)\", function () {", + " pm.expect([400, 401, 409]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "6698850c-51b4-4b49-bd43-e755a89b9d3b", + "name": "POST Onboarding — Certificate not trusted or client rejected", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "onboarding"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"onboarding.margo.org/v1alpha1\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"\"\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "704d3d46-145c-4a4d-8e45-a11098a92076", + "name": "Client certificate not trusted or client rejected.", + "code": 403, + "status": "Forbidden", + "header": [], + "body": "{\"error\": \"Certificate not trusted\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::/api/v1/onboarding - Untrusted cert returns 403 (or 400/401)\", function () {", + " pm.expect([400, 401, 403]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "11083d25-7236-471d-8455-89d8c67f9d10", + "name": "POST Capabilities — Signature verification failed", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"device.margo.org/v1alpha1\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"{{clientId}}\",\n \"vendor\": \"TestVendor\",\n \"modelNumber\": \"MDL-001\",\n \"serialNumber\": \"SN-0001\",\n \"roles\": [\"Standalone Device\"],\n \"resources\": {\n \"cpu\": { \"cores\": 4, \"architecture\": \"amd64\" },\n \"memory\": \"8Gi\",\n \"storage\": \"64Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "76dc6c15-c78c-4f1d-b9e6-b37055dec7f8", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "code": 401, + "status": "Unauthorized", + "header": [], + "body": "{\"error\": \"Signature verification failed\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../capabilities - No signature returns 400 or 401\", function () {", + " pm.expect([400, 401]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "d6472975-6b22-46b8-83fe-d730929ec369", + "name": "POST Capabilities — Client certificate not trusted or has been revoked", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"device.margo.org/v1alpha1\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"{{clientId}}\",\n \"vendor\": \"TestVendor\",\n \"modelNumber\": \"MDL-001\",\n \"serialNumber\": \"SN-0001\",\n \"roles\": [\"Standalone Device\"],\n \"resources\": {\n \"cpu\": { \"cores\": 4, \"architecture\": \"amd64\" },\n \"memory\": \"8Gi\",\n \"storage\": \"64Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "16a17a99-8569-408a-9820-02ea32ee5f4a", + "name": "Client certificate is not trusted or has been revoked.", + "code": 403, + "status": "Forbidden", + "header": [], + "body": "{\"error\": \"Certificate not trusted\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../capabilities - Untrusted cert returns 400, 401, or 403\", function () {", + " pm.expect([400, 401, 403]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "cce2e8d1-dde4-41b0-893d-6b988c353b91", + "name": "POST Capabilities — Request body includes a semantic error", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"wrong.api.version/v99\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"{clientId}\",\n \"vendor\": \"TestVendor\",\n \"modelNumber\": \"MDL-001\",\n \"serialNumber\": \"SN-0001\",\n \"roles\": [\"Standalone Device\"],\n \"resources\": {\n \"cpu\": { \"cores\": 4, \"architecture\": \"amd64\" },\n \"memory\": \"8Gi\",\n \"storage\": \"64Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "d0dbc06c-3c2c-431e-80af-99ef5baccc1b", + "name": "Request body includes a semantic error.", + "code": 422, + "status": "Unprocessable Entity", + "header": [], + "body": "{\"error\": \"Semantic validation failed\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../capabilities - Wrong apiVersion returns 400 or 422\", function () {", + " pm.expect([400, 422]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "ac5ccdb9-ba6c-4cfd-af52-1afc19860899", + "name": "GET Deployments — Wrong Accept header returns 406", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Accept", "value": "application/json" }], + "body": {} + }, + "response": [ + { + "id": "dceb4304-b240-469a-8e42-2d97d2b3bfd6", + "name": "Not Acceptable", + "code": 406, + "status": "Not Acceptable", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::.../deployments - Wrong Accept header returns 406 (or 400/500 if not implemented)\", function () {", + " pm.expect([400, 406, 500]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "2f0f025c-3bb5-4e9f-9557-83a52fdaa2c1", + "name": "POST Status — Request body includes a semantic error (invalid state)", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", "status"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" } + ] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"deployment.margo.org/v1alpha1\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"{deploymentId}\",\n \"status\": { \"state\": \"not-a-valid-state-value\" },\n \"components\": [{ \"name\": \"app\", \"state\": \"installed\" }]\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "4090c79a-2989-4b13-8823-325b34071123", + "name": "Request body includes a semantic error.", + "code": 422, + "status": "Unprocessable Entity", + "header": [], + "body": "{\"error\": \"Invalid state value\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../status - Invalid state value returns 400 or 422 (404 if no deployment)\", function () {", + " pm.expect([400, 404, 422]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "fd1f9cbf-b5ae-4562-9b11-a46cca8a9e2e", + "name": "POST Capabilities — Unknown client returns 404", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", "nonexistent-client-00000000", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"device.margo.org/v1alpha1\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"nonexistent-client-00000000\",\n \"vendor\": \"TestVendor\",\n \"modelNumber\": \"MDL-001\",\n \"serialNumber\": \"SN-0001\",\n \"roles\": [\"Standalone Device\"],\n \"resources\": {\n \"cpu\": { \"cores\": 4, \"architecture\": \"amd64\" },\n \"memory\": \"8Gi\",\n \"storage\": \"64Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "7ec7ce3c-1e7d-4ecf-8827-1a6c3151fd23", + "name": "Client not found.", + "code": 404, + "status": "Not Found", + "header": [], + "body": "{\"error\": \"Client not found\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../capabilities - Unknown clientId returns 400 or 404\", function () {", + " pm.expect([400, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + } + ] +} diff --git a/Data-Generator/wfm-supplier/groups/vendor-positive-extended/group.json b/Data-Generator/wfm-supplier/groups/vendor-positive-extended/group.json new file mode 100644 index 0000000..22b0b06 --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/vendor-positive-extended/group.json @@ -0,0 +1,40 @@ +{ + "name": "vendor-positive-extended", + "version": "1.0.0", + "persona": "wfm-supplier", + "description": "Enhanced positive conformance tests covering the full device-agent lifecycle with request chaining, ETag/304 caching, response schema validation, and all deployment status states. Uses Postman collection format — consistent with gold/silver/diamond groups.", + "FolderPath": [ + "Data-Generator/wfm-supplier/groups/vendor-positive-extended" + ], + "testCases": [ + "1f9630d3-9ee9-4477-81b4-785aef04ca6c", + "151793dc-374a-45d9-b534-1aa66082bb12", + "4d70f2af-76b1-409d-9220-20c22ca48694", + "85f90892-c936-48e8-9695-1e11b2217dbf", + "c13d8721-967c-4eae-b165-9f6bb3a198c8", + "8ad2d06e-6447-4bd5-b185-81d9f6493786", + "ba42e53d-f677-4057-a4c0-eecedfaaa1de", + "dc8c99d9-92d3-47af-bc4c-5fab6387c5ae", + "cd962676-6633-4ee0-bb06-f8099bc26ddf", + "11c8b830-8243-459b-8e33-9a02cfff69b5", + "8ac42a20-2df5-4833-bcae-3b3c28946784", + "b80a2565-a009-4372-a665-a553e2b09373", + "fd55081c-06e3-4bed-97f8-02f471a42d93", + "28dbc26f-4ae2-4257-bf1d-d4312c287639", + "5f2b74f4-5efc-4af6-9cbc-85d97190cba7", + "b16d335d-1c36-4e16-8b3f-199560dad638", + "7b1d86c7-0cce-43f0-90f8-1d9ddfb37790", + "de636126-1beb-4164-956a-266bd2816305", + "ce5d181e-ff53-4812-b1fd-c55defa1b2c7", + "29a4be4e-30ce-453d-a326-6c2d0f1485bd", + "5e4f3c28-0f15-4025-ba58-36000534bc69", + "68506fd7-619e-45d0-80e5-818aa3f64683", + "5270041c-b745-4a3f-b49b-e47277460af3", + "3971b5f8-d6fd-47b2-af9a-82ba6f0e150e", + "5b2d7fe3-2e75-4d5d-8d95-db722d22ce02", + "d968773e-882d-4200-bb0b-7685d8aea928", + "1b5eb864-a7c5-4004-9044-a8094db8853e", + "19da612a-0c6d-4655-97ca-951e5bd6796e", + "d2c5fbf6-0b87-4108-a709-f73c810ea74f" + ] +} diff --git a/Data-Generator/wfm-supplier/groups/vendor-positive-extended/postman_collection.json b/Data-Generator/wfm-supplier/groups/vendor-positive-extended/postman_collection.json new file mode 100644 index 0000000..2a2cb2d --- /dev/null +++ b/Data-Generator/wfm-supplier/groups/vendor-positive-extended/postman_collection.json @@ -0,0 +1,673 @@ +{ + "info": { + "_postman_id": "d2c5fbf6-0b87-4108-a709-f73c810ea74f", + "name": "Margo WFM Supplier — Enhanced Positive Conformance Tests", + "description": "Comprehensive positive conformance tests for the WFM Supplier persona. Tests the full device-agent lifecycle (onboarding → capabilities → deployments → status) with request chaining, deep schema validation, ETag/304 caching, and multiple deployment status states. clientId is extracted from POST /onboarding and threaded through all subsequent steps automatically.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "id": "1f9630d3-9ee9-4477-81b4-785aef04ca6c", + "name": "GET Root CA Certificate — Verify structure", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "onboarding", "certificate"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [] + }, + "header": [{ "key": "Accept", "value": "application/json" }], + "body": {} + }, + "response": [ + { + "id": "151793dc-374a-45d9-b534-1aa66082bb12", + "name": "Root CA certificate", + "code": 200, + "status": "OK", + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": "{\"certificate\": \"\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/onboarding/certificate - Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test(\"[GET]::/api/v1/onboarding/certificate - Response has certificate field\", function () {", + " const body = pm.response.json();", + " pm.expect(body).to.have.property('certificate');", + " pm.expect(body.certificate).to.be.a('string');", + "});" + ] + } + } + ] + }, + { + "id": "4d70f2af-76b1-409d-9220-20c22ca48694", + "name": "POST Onboarding — Extract clientId for all subsequent requests", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "onboarding"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [] + }, + "header": [ + { "key": "Content-Type", "value": "application/json" }, + { "key": "Accept", "value": "application/json" } + ], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"onboarding.margo.org/v1alpha1\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"\"\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "85f90892-c936-48e8-9695-1e11b2217dbf", + "name": "New client onboarded successfully.", + "code": 201, + "status": "Created", + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": "{\"clientId\": \"client-abc123\"}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::/api/v1/onboarding - Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});", + "pm.test(\"[POST]::/api/v1/onboarding - Response contains clientId\", function () {", + " const body = pm.response.json();", + " pm.expect(body).to.have.property('clientId');", + " pm.expect(body.clientId).to.be.a('string');", + " pm.environment.set('clientId', body.clientId);", + "});" + ] + } + } + ] + }, + { + "id": "c13d8721-967c-4eae-b165-9f6bb3a198c8", + "name": "POST Capabilities — Initial device registration", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"device.margo.org/v1alpha1\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"{{clientId}}\",\n \"vendor\": \"ConformanceTestVendor\",\n \"modelNumber\": \"MDL-CONFORM-001\",\n \"serialNumber\": \"SN-CONFORM-0001\",\n \"roles\": [\"Standalone Device\"],\n \"resources\": {\n \"cpu\": { \"cores\": 4, \"architecture\": \"amd64\" },\n \"memory\": \"8Gi\",\n \"storage\": \"64Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "8ad2d06e-6447-4bd5-b185-81d9f6493786", + "name": "Capabilities reported successfully", + "code": 201, + "status": "Created", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::/api/v1/clients/:clientId/capabilities - Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ] + } + } + ] + }, + { + "id": "ba42e53d-f677-4057-a4c0-eecedfaaa1de", + "name": "PUT Capabilities — Hardware update accepted", + "request": { + "method": "PUT", + "url": { + "path": ["api", "v1", "clients", ":clientId", "capabilities"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"device.margo.org/v1alpha1\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"{{clientId}}\",\n \"vendor\": \"ConformanceTestVendor\",\n \"modelNumber\": \"MDL-CONFORM-001\",\n \"serialNumber\": \"SN-CONFORM-0001\",\n \"roles\": [\"Standalone Device\", \"Cluster Leader\"],\n \"resources\": {\n \"cpu\": { \"cores\": 8, \"architecture\": \"amd64\" },\n \"memory\": \"16Gi\",\n \"storage\": \"128Gi\",\n \"interfaces\": [{ \"type\": \"ethernet\" }, { \"type\": \"wifi\" }],\n \"peripherals\": []\n }\n }\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "dc8c99d9-92d3-47af-bc4c-5fab6387c5ae", + "name": "Capabilities updated successfully", + "code": 201, + "status": "Created", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[PUT]::/api/v1/clients/:clientId/capabilities - Status code is 201\", function () {", + " pm.response.to.have.status(201);", + "});" + ] + } + } + ] + }, + { + "id": "cd962676-6633-4ee0-bb06-f8099bc26ddf", + "name": "GET Deployments — Schema validation and ETag extraction", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [{ "key": "Accept", "value": "application/vnd.margo.manifest.v1+json" }], + "body": {} + }, + "response": [ + { + "id": "11c8b830-8243-459b-8e33-9a02cfff69b5", + "name": "Current deployment manifest", + "code": 200, + "status": "OK", + "header": [ + { "key": "Content-Type", "value": "application/vnd.margo.manifest.v1+json" }, + { "key": "ETag", "value": "\"abc123\"" } + ], + "body": "{\"manifestVersion\": 1, \"bundle\": null, \"deployments\": []}", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments - manifestVersion is a number\", function () {", + " const body = pm.response.json();", + " pm.expect(body).to.have.property('manifestVersion');", + " pm.expect(body.manifestVersion).to.be.a('number');", + "});", + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments - deployments is an array\", function () {", + " const body = pm.response.json();", + " pm.expect(body).to.have.property('deployments');", + " pm.expect(body.deployments).to.be.an('array');", + "});", + "if (pm.response.headers.get('ETag')) {", + " pm.environment.set('manifestEtag', pm.response.headers.get('ETag'));", + "}", + "const body = pm.response.json();", + "if (body.deployments && body.deployments.length > 0) {", + " pm.environment.set('deploymentId', body.deployments[0].deploymentId);", + " pm.environment.set('deploymentDigest', body.deployments[0].digest);", + "}", + "if (body.bundle) {", + " pm.environment.set('bundleDigest', body.bundle.digest);", + "}" + ] + } + } + ] + }, + { + "id": "8ac42a20-2df5-4833-bcae-3b3c28946784", + "name": "GET Deployments — If-None-Match ETag returns 304 Not Modified", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [{ "key": "clientId", "value": "{{clientId}}" }] + }, + "header": [ + { "key": "Accept", "value": "application/vnd.margo.manifest.v1+json" }, + { "key": "If-None-Match", "value": "{{manifestEtag}}" } + ], + "body": {} + }, + "response": [ + { + "id": "b80a2565-a009-4372-a665-a553e2b09373", + "name": "Not Modified", + "code": 304, + "status": "Not Modified", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments - ETag match returns 304 or 200\", function () {", + " pm.expect([200, 304]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "fd55081c-06e3-4bed-97f8-02f471a42d93", + "name": "GET Bundle — Content-Type and cache headers", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "bundles", ":bundleDigest"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "bundleDigest", "value": "{{bundleDigest}}" } + ] + }, + "header": [], + "body": {} + }, + "response": [ + { + "id": "28dbc26f-4ae2-4257-bf1d-d4312c287639", + "name": "Bundle archive", + "code": 200, + "status": "OK", + "header": [ + { "key": "Content-Type", "value": "application/vnd.margo.bundle.v1+tar+gzip" }, + { "key": "ETag", "value": "\"bundle-abc\"" }, + { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } + ], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:bundleDigest - Status 200 or 404\", function () {", + " pm.expect([200, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "5f2b74f4-5efc-4af6-9cbc-85d97190cba7", + "name": "GET Bundle — If-None-Match ETag returns 304 Not Modified", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "bundles", ":bundleDigest"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "bundleDigest", "value": "{{bundleDigest}}" } + ] + }, + "header": [{ "key": "If-None-Match", "value": "{{bundleEtag}}" }], + "body": {} + }, + "response": [ + { + "id": "b16d335d-1c36-4e16-8b3f-199560dad638", + "name": "Not Modified", + "code": 304, + "status": "Not Modified", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:bundleDigest - ETag match returns 200, 304, or 404\", function () {", + " pm.expect([200, 304, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "7b1d86c7-0cce-43f0-90f8-1d9ddfb37790", + "name": "GET Deployment Manifest — YAML content", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", ":deploymentDigest"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" }, + { "key": "deploymentDigest", "value": "{{deploymentDigest}}" } + ] + }, + "header": [], + "body": {} + }, + "response": [ + { + "id": "de636126-1beb-4164-956a-266bd2816305", + "name": "Deployment manifest YAML", + "code": 200, + "status": "OK", + "header": [ + { "key": "Content-Type", "value": "application/yaml" }, + { "key": "ETag", "value": "\"manifest-abc\"" }, + { "key": "Cache-Control", "value": "public, max-age=31536000, immutable" } + ], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Status 200 or 404\", function () {", + " pm.expect([200, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "ce5d181e-ff53-4812-b1fd-c55defa1b2c7", + "name": "GET Deployment Manifest — If-None-Match ETag returns 304 Not Modified", + "request": { + "method": "GET", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", ":deploymentDigest"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" }, + { "key": "deploymentDigest", "value": "{{deploymentDigest}}" } + ] + }, + "header": [{ "key": "If-None-Match", "value": "{{deploymentEtag}}" }], + "body": {} + }, + "response": [ + { + "id": "29a4be4e-30ce-453d-a326-6c2d0f1485bd", + "name": "Not Modified", + "code": 304, + "status": "Not Modified", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - ETag match returns 200, 304, or 404\", function () {", + " pm.expect([200, 304, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "5e4f3c28-0f15-4025-ba58-36000534bc69", + "name": "POST Status — pending state accepted", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", "status"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" } + ] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"deployment.margo.org/v1alpha1\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"{{deploymentId}}\",\n \"status\": { \"state\": \"pending\" },\n \"components\": [{ \"name\": \"app-component-1\", \"state\": \"pending\" }]\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "68506fd7-619e-45d0-80e5-818aa3f64683", + "name": "Status updated successfully", + "code": 200, + "status": "OK", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../status - 'pending' state accepted (200, 400, or 404)\", function () {", + " pm.expect([200, 400, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "5270041c-b745-4a3f-b49b-e47277460af3", + "name": "POST Status — installing state accepted", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", "status"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" } + ] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"deployment.margo.org/v1alpha1\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"{{deploymentId}}\",\n \"status\": { \"state\": \"installing\" },\n \"components\": [{ \"name\": \"app-component-1\", \"state\": \"installing\" }]\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "3971b5f8-d6fd-47b2-af9a-82ba6f0e150e", + "name": "Status updated successfully", + "code": 200, + "status": "OK", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../status - 'installing' state accepted (200, 400, or 404)\", function () {", + " pm.expect([200, 400, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "5b2d7fe3-2e75-4d5d-8d95-db722d22ce02", + "name": "POST Status — installed state accepted", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", "status"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" } + ] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"deployment.margo.org/v1alpha1\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"{{deploymentId}}\",\n \"status\": { \"state\": \"installed\" },\n \"components\": [{ \"name\": \"app-component-1\", \"state\": \"installed\" }]\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "d968773e-882d-4200-bb0b-7685d8aea928", + "name": "Status updated successfully", + "code": 200, + "status": "OK", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../status - 'installed' state accepted (200, 400, or 404)\", function () {", + " pm.expect([200, 400, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + }, + { + "id": "1b5eb864-a7c5-4004-9044-a8094db8853e", + "name": "POST Status — failed state with error details accepted", + "request": { + "method": "POST", + "url": { + "path": ["api", "v1", "clients", ":clientId", "deployments", ":deploymentId", "status"], + "host": ["{{baseUrl}}"], + "query": [], + "variable": [ + { "key": "clientId", "value": "{{clientId}}" }, + { "key": "deploymentId", "value": "{{deploymentId}}" } + ] + }, + "header": [{ "key": "Content-Type", "value": "application/json" }], + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"deployment.margo.org/v1alpha1\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"{{deploymentId}}\",\n \"status\": {\n \"state\": \"failed\",\n \"error\": { \"code\": \"IMAGE_PULL_ERROR\", \"source\": \"runtime\", \"message\": \"Failed to pull image from registry\" }\n },\n \"components\": [\n { \"name\": \"app-component-1\", \"state\": \"failed\", \"error\": { \"code\": \"PULL_BACKOFF\", \"source\": \"docker\", \"message\": \"Back-off pulling image\" } }\n ]\n}", + "options": { "raw": { "headerFamily": "json", "language": "json" } } + } + }, + "response": [ + { + "id": "19da612a-0c6d-4655-97ca-951e5bd6796e", + "name": "Status updated successfully", + "code": 200, + "status": "OK", + "header": [], + "body": "", + "cookie": [], + "_": { "postman_previewlanguage": "json" } + } + ], + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"[POST]::.../status - 'failed' state with error details accepted (200, 400, or 404)\", function () {", + " pm.expect([200, 400, 404]).to.include(pm.response.code);", + "});" + ] + } + } + ] + } + ] +} diff --git a/Data-Generator/wfm-supplier/newman-data/certs/ca-cert.pem b/Data-Generator/wfm-supplier/newman-data/certs/ca-cert.pem new file mode 100644 index 0000000..bd47687 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/certs/ca-cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDkTCCAnkCFC2Rae4sGJ2mwHHN4FAobNytTTNfMA0GCSqGSIb3DQEBCwUAMIGE +MQswCQYDVQQGEwJJTjEMMAoGA1UECAwDR0dOMRowGAYDVQQHDBFTb21lIEFCQyBM +b2NhdGlvbjEOMAwGA1UECgwFTWFyZ28xGTAXBgNVBAMMEHN5bXBob255Lm1hY2hp +bmUxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMB4XDTI2MDYwODEw +MjY1N1oXDTI3MDYwODEwMjY1N1owgYQxCzAJBgNVBAYTAklOMQwwCgYDVQQIDANH +R04xGjAYBgNVBAcMEVNvbWUgQUJDIExvY2F0aW9uMQ4wDAYDVQQKDAVNYXJnbzEZ +MBcGA1UEAwwQc3ltcGhvbnkubWFjaGluZTEgMB4GCSqGSIb3DQEJARYRYWRtaW5A +ZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQamzg +GQZjiZSnsbcFPuyJ1BpYdoTKRyBAZvF+oAVy/U9GykERAfsnb9reiAePGDGLgrQp +7xkUyMrMuU5TJuxpPqaFxsmoAWjvPr6tct9ZmT75yDsQTxDQKNAYJZ3rA2glGf95 +Hj0Fl/e5lzq+xj5+qSLY/lsWVwTSuJ57mLSgFEO+dxq8Y40qqopOAvX/EiQSHVzn +C20gKIJ0GBdHFjN0/Ja+4mhm31gf6IXI2BrlJ1FHFaVIBJ5f3oVtIcPFwslVozQ1 +Z6W5WvHZrQEzD0yg8I6YIirACNaYHHCs2BkYF3pLIx/hkHV+cunr0trv8QymTH3m +mhli25AgJzLU/4LLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIByUqMRZq1HE+qN +hr/KxX2f7VxAiBfzdd6RfwFvs+ufSWT1AdeTM7m9a5k4j4JxyBBcaw75lRTc5A0c +1bWYtiOe0bFX4DDaw/C5neQZnP3L9jlgp7+Cf9VjtQUZEXnZvCyYLxn83gQs1sgT +cwEaE8HWaB9PRvf8DxGFlP6J1sK8Nwbi2VjlGTwEFJpUNehQbTL6GhaDIDGCHICD +uyDHtT0NERlg4YLbV2QaOC2MPoB0fECm/4Gghrp0k6dWaNhqAZ0wIh/7DYFm54x5 +KzTuQ9HnhiNyr78rqytGjVuUOEg3c9A9RT7+7CWbJk98WcBeIfpFX3+fwn35fD9P +WMc6M9Y= +-----END CERTIFICATE----- diff --git a/Data-Generator/wfm-supplier/newman-data/certs/device-cert.pem b/Data-Generator/wfm-supplier/newman-data/certs/device-cert.pem new file mode 100644 index 0000000..b1ae81d --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/certs/device-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSDCCAe2gAwIBAgIUMLM09qc9xcw+DopQU8ZcG8AyQYgwCgYIKoZIzj0EAwIw +eTELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0dHTjERMA8GA1UEBwwIU2VjdG9yNDgx +DjAMBgNVBAoMBU1hcmdvMRQwEgYDVQQLDAtDb25mb3JtYW5jZTEjMCEGA1UEAwwa +ZGV2aWNlLTE3ODYzNjUzNTM1NDMtMjQ0MzEwHhcNMjYwODEwMTIzNTUzWhcNMjcw +ODEwMTIzNTUzWjB5MQswCQYDVQQGEwJJTjEMMAoGA1UECAwDR0dOMREwDwYDVQQH +DAhTZWN0b3I0ODEOMAwGA1UECgwFTWFyZ28xFDASBgNVBAsMC0NvbmZvcm1hbmNl +MSMwIQYDVQQDDBpkZXZpY2UtMTc4NjM2NTM1MzU0My0yNDQzMTBZMBMGByqGSM49 +AgEGCCqGSM49AwEHA0IABDV0NM+y14NYz3D9czYgilGEdzlLJlMjfF9OlFcwcY+k +tXZPXGs6nsH8scG89aFv36Axg7FHte35T1gMKnFvwsajUzBRMB0GA1UdDgQWBBT6 +VR+c0PvAkEv40NMlGBrTM4U2ejAfBgNVHSMEGDAWgBT6VR+c0PvAkEv40NMlGBrT +M4U2ejAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCFHftsZvSi +16iTwgWrzemwITGsibYYyLNT8VltYyUBlgIhANHsnEBThQOUpAYmjcebeJqfb/v4 +MGVvxLnkfpwo9T4x +-----END CERTIFICATE----- diff --git a/Data-Generator/wfm-supplier/newman-data/certs/device.key b/Data-Generator/wfm-supplier/newman-data/certs/device.key new file mode 100644 index 0000000..57f9d1e --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/certs/device.key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEID3JZExcxVNQcQKm4cCCeizntOKT+w3odhj/Mg4wuRXZoAoGCCqGSM49 +AwEHoUQDQgAENXQ0z7LXg1jPcP1zNiCKUYR3OUsmUyN8X06UVzBxj6S1dk9cazqe +wfyxwbz1oW/foDGDsUe17flPWAwqcW/Cxg== +-----END EC PRIVATE KEY----- diff --git a/Data-Generator/wfm-supplier/newman-data/device-agent.env.json b/Data-Generator/wfm-supplier/newman-data/device-agent.env.json new file mode 100644 index 0000000..7ab4314 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/device-agent.env.json @@ -0,0 +1,71 @@ +{ + "id": "margo-wfm-supplier-env", + "name": "Margo WFM Supplier", + "values": [ + { + "key": "baseUrl", + "value": "https://localhost:3001/v1alpha2/margo", + "enabled": true + }, + { + "key": "deviceId", + "value": "device-1779864226", + "enabled": true + }, + { + "key": "clientId", + "value": "client-cb336dc9443afc98-1779469290", + "enabled": true + }, + { + "key": "certificate", + "value": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOVENDQWR1Z0F3SUJBZ0lVTGhEa2FvbW15ZjdmOS80V2VTd0VhbWlneXY4d0NnWUlLb1pJemowRUF3SXcKY0RFTE1Ba0dBMVVFQmhNQ1NVNHhEREFLQmdOVkJBZ01BMGRIVGpFUk1BOEdBMVVFQnd3SVUyVmpkRzl5TkRneApEakFNQmdOVkJBb01CVTFoY21kdk1SUXdFZ1lEVlFRTERBdERiMjVtYjNKdFlXNWpaVEVhTUJnR0ExVUVBd3dSClpHVjJhV05sTFRFM056azROalF5TWpZd0hoY05Nall3TlRJM01EWTBNelEyV2hjTk1qY3dOVEkzTURZME16UTIKV2pCd01Rc3dDUVlEVlFRR0V3SkpUakVNTUFvR0ExVUVDQXdEUjBkT01SRXdEd1lEVlFRSERBaFRaV04wYjNJMApPREVPTUF3R0ExVUVDZ3dGVFdGeVoyOHhGREFTQmdOVkJBc01DME52Ym1admNtMWhibU5sTVJvd0dBWURWUVFECkRCRmtaWFpwWTJVdE1UYzNPVGcyTkRJeU5qQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJQUXIKY1JweVM0M0RHckRydk9PY1pRZlFjbldoVUdUamNrQ1hTcDduZFczL09UQ3UwYkQzSVVwZFpwTks1VTdUMEJkeApjSzh5VFNzV251YStYWnJnZUx5alV6QlJNQjBHQTFVZERnUVdCQlJpNW84UkFXL0NISXFidmhFOTN5RWR1MHZICjVEQWZCZ05WSFNNRUdEQVdnQlJpNW84UkFXL0NISXFidmhFOTN5RWR1MHZINURBUEJnTlZIUk1CQWY4RUJUQUQKQVFIL01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQ1Y0VHMxeUlrbkM1VlRaZjBDNnQwVEtsaVZkR0d5elhjcgpaS1lXSTNLUi93SWdSLzJwM2FEaUJOVGNTUjMrWWpNNFhZQUdabEczL0cxNG9PWklmMWw3V0FVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==", + "enabled": true + }, + { + "key": "onboardingRequest", + "value": "{\"apiVersion\":\"onboarding.margo.org/v1alpha1\",\"kind\":\"OnboardingRequest\",\"certificate\":\"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNOVENDQWR1Z0F3SUJBZ0lVTGhEa2FvbW15ZjdmOS80V2VTd0VhbWlneXY4d0NnWUlLb1pJemowRUF3SXcKY0RFTE1Ba0dBMVVFQmhNQ1NVNHhEREFLQmdOVkJBZ01BMGRIVGpFUk1BOEdBMVVFQnd3SVUyVmpkRzl5TkRneApEakFNQmdOVkJBb01CVTFoY21kdk1SUXdFZ1lEVlFRTERBdERiMjVtYjNKdFlXNWpaVEVhTUJnR0ExVUVBd3dSClpHVjJhV05sTFRFM056azROalF5TWpZd0hoY05Nall3TlRJM01EWTBNelEyV2hjTk1qY3dOVEkzTURZME16UTIKV2pCd01Rc3dDUVlEVlFRR0V3SkpUakVNTUFvR0ExVUVDQXdEUjBkT01SRXdEd1lEVlFRSERBaFRaV04wYjNJMApPREVPTUF3R0ExVUVDZ3dGVFdGeVoyOHhGREFTQmdOVkJBc01DME52Ym1admNtMWhibU5sTVJvd0dBWURWUVFECkRCRmtaWFpwWTJVdE1UYzNPVGcyTkRJeU5qQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJQUXIKY1JweVM0M0RHckRydk9PY1pRZlFjbldoVUdUamNrQ1hTcDduZFczL09UQ3UwYkQzSVVwZFpwTks1VTdUMEJkeApjSzh5VFNzV251YStYWnJnZUx5alV6QlJNQjBHQTFVZERnUVdCQlJpNW84UkFXL0NISXFidmhFOTN5RWR1MHZICjVEQWZCZ05WSFNNRUdEQVdnQlJpNW84UkFXL0NISXFidmhFOTN5RWR1MHZINURBUEJnTlZIUk1CQWY4RUJUQUQKQVFIL01Bb0dDQ3FHU000OUJBTUNBMGdBTUVVQ0lRQ1Y0VHMxeUlrbkM1VlRaZjBDNnQwVEtsaVZkR0d5elhjcgpaS1lXSTNLUi93SWdSLzJwM2FEaUJOVGNTUjMrWWpNNFhZQUdabEczL0cxNG9PWklmMWw3V0FVPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\"}\n", + "enabled": true + }, + { + "key": "capabilitiesRequest", + "value": "{\"apiVersion\":\"device.margo.org/v1alpha1\",\"kind\":\"DeviceCapabilitiesManifest\",\"properties\":{\"id\":\"device-1779864226\",\"vendor\":\"Margo Vendor\",\"modelNumber\":\"MARGO-MODEL-01\",\"serialNumber\":\"SN-device-1779864226\",\"roles\":[\"Standalone Device\"],\"resources\":{\"cpu\":{\"cores\":4,\"architecture\":\"arm64\"},\"memory\":\"8Gi\",\"storage\":\"64Gi\",\"interfaces\":[{\"type\":\"ethernet\"}],\"peripherals\":[]}}}\n", + "enabled": true + }, + { + "key": "capabilitiesUpdateRequest", + "value": "{\"apiVersion\":\"device.margo.org/v1alpha1\",\"kind\":\"DeviceCapabilitiesManifest\",\"properties\":{\"id\":\"device-1779864226\",\"vendor\":\"Margo Vendor\",\"modelNumber\":\"MARGO-MODEL-01\",\"serialNumber\":\"SN-device-1779864226\",\"roles\":[\"Standalone Device\",\"Cluster Leader\"],\"resources\":{\"cpu\":{\"cores\":8,\"architecture\":\"amd64\"},\"memory\":\"16Gi\",\"storage\":\"128Gi\",\"interfaces\":[{\"type\":\"ethernet\"},{\"type\":\"wifi\"}],\"peripherals\":[]}}}\n", + "enabled": true + }, + { + "key": "statusRequest", + "value": "{\"apiVersion\":\"deployment.margo.org/v1alpha1\",\"kind\":\"DeploymentStatusManifest\",\"deploymentId\":\"demo-deployment-001\",\"components\":[{\"name\":\"app-component-1\",\"state\":\"installed\"}],\"status\":{\"state\":\"installed\"}}\n", + "enabled": true + }, + { + "key": "deploymentId", + "value": "deployment-conformance-001", + "enabled": true + }, + { + "key": "manifestEtag", + "value": "", + "enabled": true + }, + { + "key": "digest", + "value": "sha256:abcd1234", + "enabled": true + }, + { + "key": "bundleDigest", + "value": "sha256:bundle5678", + "enabled": true + }, + { + "key": "deploymentDigest", + "value": "sha256:deploy9012", + "enabled": true + } + ] +} diff --git a/Data-Generator/wfm-supplier/newman-data/device-agent.iteration.json b/Data-Generator/wfm-supplier/newman-data/device-agent.iteration.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/device-agent.iteration.json @@ -0,0 +1 @@ +[] diff --git a/Data-Generator/wfm-supplier/newman-data/execution.log b/Data-Generator/wfm-supplier/newman-data/execution.log new file mode 100644 index 0000000..10009ac --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/execution.log @@ -0,0 +1,45 @@ +[2026-05-21 18:41:05] Starting workload execution phase +[2026-05-21 18:41:05] Device ID: device-1779388863 +[2026-05-21 18:41:05] Base URL: https://symphony.machine:8082/v1alpha2/margo +[2026-05-21 18:41:05] Client ID: client-54a95263aef07cd9-1779388865 +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] Phase 1: Query deployments from WFM +[2026-05-21 18:41:05] ================================== +[2026-05-21 18:41:05] Requesting: GET /api/v1/clients/client-54a95263aef07cd9-1779388865/deployments +✅ Received response (size: 98 bytes) +✅ Found 0 deployments +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] Phase 2: Retrieve deployment bundles +[2026-05-21 18:41:05] ==================================== +[2026-05-21 18:41:05] Requesting: GET /api/v1/clients/client-54a95263aef07cd9-1779388865/bundles/null +✅ Received response (size: 37 bytes) +✅ Retrieved bundle details +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] Phase 3: Execute workloads in Docker +[2026-05-21 18:41:05] ==================================== +[2026-05-21 18:41:05] Workloads array format detected (legacy) +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] Phase 4: Verify deployed containers +[2026-05-21 18:41:05] ==================================== +⚠️ No containers executed +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] Phase 5: Report deployment status to WFM +[2026-05-21 18:41:05] ======================================== +[2026-05-21 18:41:05] Requesting: POST /api/v1/clients/client-54a95263aef07cd9-1779388865/deployments/null/status +✅ Received response (size: 37 bytes) +✅ Deployment status reported to WFM +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] ================================================== +[2026-05-21 18:41:05] Execution Summary +[2026-05-21 18:41:05] ================================================== +[2026-05-21 18:41:05] Device ID: device-1779388863 +[2026-05-21 18:41:05] Client ID: client-54a95263aef07cd9-1779388865 +[2026-05-21 18:41:05] Deployment ID: null +[2026-05-21 18:41:05] Containers executed: 0 +[2026-05-21 18:41:05] Failed executions: 0 +[2026-05-21 18:41:05] Execution log: newman-data/execution.log +[2026-05-21 18:41:05] +[2026-05-21 18:41:05] To clean up deployed containers: +[2026-05-21 18:41:05] ./4-cleanup.sh +[2026-05-21 18:41:05] +✅ Workload execution phase complete diff --git a/Data-Generator/wfm-supplier/newman-data/responses/bundle-details.json b/Data-Generator/wfm-supplier/newman-data/responses/bundle-details.json new file mode 100644 index 0000000..11b1678 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/responses/bundle-details.json @@ -0,0 +1 @@ +{"Error":"missing signature headers"} \ No newline at end of file diff --git a/Data-Generator/wfm-supplier/newman-data/responses/deployments-query.json b/Data-Generator/wfm-supplier/newman-data/responses/deployments-query.json new file mode 100644 index 0000000..9bb6d90 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/responses/deployments-query.json @@ -0,0 +1 @@ +{"Error":"Unknown State: 406: The accept header should be application/vnd.margo.manifest.v1+json"} \ No newline at end of file diff --git a/Data-Generator/wfm-supplier/newman-data/responses/status-report.json b/Data-Generator/wfm-supplier/newman-data/responses/status-report.json new file mode 100644 index 0000000..11b1678 --- /dev/null +++ b/Data-Generator/wfm-supplier/newman-data/responses/status-report.json @@ -0,0 +1 @@ +{"Error":"missing signature headers"} \ No newline at end of file diff --git a/Data-Generator/wfm-supplier/postman_collection.json b/Data-Generator/wfm-supplier/postman_collection.json new file mode 100644 index 0000000..7f00683 --- /dev/null +++ b/Data-Generator/wfm-supplier/postman_collection.json @@ -0,0 +1,2819 @@ +{ + "_": { + "postman_id": "2a506b55-47f7-4ee0-87e2-4e976e3cd0f4" + }, + "item": [ + { + "id": "e54470f7-ae5d-4f49-a54b-dffc6fc633bd", + "name": "Download Root CA certificate", + "request": { + "name": "Download Root CA certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "GET", + "body": {} + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "08241464-61af-4eaa-a668-057dfebe9017", + "name": "Root CA certificate", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"certificate\": \"nisi cupidatat velit\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "55e2e937-2768-492f-abce-81bda6d0332b", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/onboarding/certificate - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/onboarding/certificate - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/onboarding/certificate - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"properties\":{\"certificate\":{\"type\":\"string\",\"description\":\"Base64-encoded certificate text\"}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/onboarding/certificate - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "0ee65ef4-cd28-4503-bb69-dff391976201", + "name": "Complete onboarding with client certificate", + "request": { + "name": "Complete onboarding with client certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"dolor laboris\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"labore labo\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "d73c2ad6-8472-448d-bcde-67084388de7f", + "name": "New client onboarded successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"dolor laboris\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"labore labo\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"clientId\": \"cupidatat Excepteur consequat et reprehenderit\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "ec64ac1b-2cdd-437c-b91d-0b1f2519b789", + "name": "Invalid certificate format or structure.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"dolor laboris\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"labore labo\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Invalid certificate\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "8bdbc46e-ab76-4e37-a23b-a47012188184", + "name": "Client certificate not trusted or client rejected.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"dolor laboris\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"labore labo\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Client rejected\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "94920bdf-69db-4d1c-8ca4-089f7be46658", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/onboarding - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[POST]::/api/v1/onboarding - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[POST]::/api/v1/onboarding - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"properties\":{\"clientId\":{\"type\":\"string\"}},\"type\":\"object\"}\n\n// Validate if response matches JSON schema \npm.test(\"[POST]::/api/v1/onboarding - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "cf8df6cf-4f3c-4b70-afe3-1e485d9a80a0", + "name": "Report device capabilities", + "request": { + "name": "Report device capabilities", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "y/G", + "key": "deviceId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "7077206f-c1dc-48d8-8d19-2bb9506b2f6a", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "5692eef3-bc50-4e8e-9497-a01dfb0c9b47", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "2c67fa02-97c9-4887-8030-e5888c34e3d8", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "ca258734-81e6-491e-b97a-cbab702bcb04", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "4a7d387a-e48d-4a26-9bfb-f0cff777263e", + "name": "No client with the given `clientID` was found.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "4f57d81f-16a1-47e0-a5d0-9db0d2195f69", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "535b60b9-384c-4320-bdb0-782127a38bbe", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/capabilities/:deviceId - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "d7ff1382-6fc4-4a80-91f2-7612529dc771", + "name": "Update device capabilities (Update)", + "request": { + "name": "Update device capabilities (Update)", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "y/G", + "key": "deviceId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "938b85c5-639c-412f-b43b-de71d396dbe9", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "575e74bb-fd10-4ce8-916b-2e68596664df", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "17c82ae7-b114-4c8c-b700-0a98fc6ce8b3", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6d4211e5-751d-4adb-9ba2-c9a07ef14c3f", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "e55a15c4-bf0a-4e32-8be7-485a07ee64cf", + "name": "No client with the given `clientID` was found.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "9dfd8ec8-2023-4bac-9b91-05fd870b6147", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"magna aliqua Ut id\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"uvR\",\n \"vendor\": \"voluptate magna laboris do\",\n \"modelNumber\": \"reprehenderit nulla dolore\",\n \"serialNumber\": \"dolor commodo\",\n \"cpus\": [\n {\n \"cores\": 50321535.96236482,\n \"architecture\": \"arm64\"\n },\n {\n \"cores\": 72159453.21566576,\n \"architecture\": \"arm\"\n }\n ],\n \"memory\": \"non ea\",\n \"storage\": \"laboris veniam sit\",\n \"peripherals\": [\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"culpa ut labore\",\n \"model\": \"enim amet Duis sunt\"\n },\n {\n \"type\": \"speaker\",\n \"manufacturer\": \"in culpa\",\n \"model\": \"elit nulla\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"bluetooth\"\n },\n {\n \"type\": \"usb\"\n }\n ],\n \"otelCollector\": false,\n \"supportedRuntimes\": [\n \"oci\"\n ],\n \"supportedDeploymentTypes\": [\n \"compose\"\n ]\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "31b413f0-63c1-4e44-a924-d04f55800728", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[PUT]::/api/v1/clients/:clientId/capabilities/:deviceId - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "a4ed3fbc-80a9-444e-ab33-adabef561fe0", + "name": "Remove device (Unregister)", + "request": { + "name": "Remove device (Unregister)", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "y/G", + "key": "deviceId" + } + ] + }, + "method": "DELETE", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f78be0ec-44ed-4507-8392-c7e91d5c721b", + "name": "Device capabilities removed successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "DELETE", + "body": {} + }, + "status": "No Content", + "code": 204, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "9f192896-eea5-44e1-ab44-48f62700c6ed", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "DELETE", + "body": {} + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "807d8247-30b2-4e9e-a5ad-08deb4ce5dde", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "DELETE", + "body": {} + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "94cb4480-eec6-47aa-8d9d-da051d5ee3b9", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "DELETE", + "body": {} + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "9eb3b47a-bcd0-419d-a645-6c04ac1addf5", + "name": "Client or device not found.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities", + ":deviceId" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "DELETE", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "f2d78760-031b-4bd6-b1b6-c369c9819bd7", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[DELETE]::/api/v1/clients/:clientId/capabilities/:deviceId - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response has empty Body \npm.test(\"[DELETE]::/api/v1/clients/:clientId/capabilities/:deviceId - Response has empty Body\", function () {\n pm.response.to.not.be.withBody;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "8d3d2e65-83df-4423-a137-c1a0c8561c87", + "name": "Retrieve bundle information for a specific device and digest", + "request": { + "name": "Retrieve bundle information for a specific device and digest", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the device-client", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "458c00eb-46a0-44d5-8315-e63cc47624a9", + "name": "Bundle archive (immutable)", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "eu ut" + } + ], + "body": "eiusmod ", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "ddfd3ad8-7420-4151-ac6c-e057e1f4b7d4", + "name": "Representation not modified", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "615289a6-56cc-45cc-be6d-c7df6cb438d0", + "name": "Invalid request.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "27ead7c4-4e84-4d9a-a704-a80939c96e12", + "name": "Bundle not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "bc5ec86c-ed25-4b6f-bee9-1d1aa590d43d", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Content-Type is application/vnd.margo.bundle.v1+tar+gzip\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.bundle.v1+tar+gzip\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "914524dc-4775-4399-9096-79e98fffabf9", + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "request": { + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) The unique identifier of the Edge Compute Device making the request", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "5052a880-8f9a-4367-877c-53538e434b85", + "name": "Manifest returned in the negotiated format", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "disabled": true, + "description": { + "content": "Format of the returned manifest", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "eu ut" + } + ], + "body": "{\n \"manifestVersion\": -36137712.95062795,\n \"bundle\": null,\n \"deployments\": [\n {\n \"deploymentId\": \"in occaecat incididunt\",\n \"digest\": \"ea nostrud\",\n \"url\": \"quis pariatur voluptate\",\n \"sizeBytes\": -5934590.525234193\n },\n {\n \"deploymentId\": \"nisi veniam in occaecat\",\n \"digest\": \"dolor\",\n \"url\": \"dolore\",\n \"sizeBytes\": -57406864.85500705\n }\n ],\n \"bundle.mediaType\": 59093791,\n \"bundle.digest\": false,\n \"bundle.url\": 6735648\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "22ba4662-4172-441d-bbe6-046352733c74", + "name": "Not Modified - Manifest has not changed", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "4d361413-6722-41e4-b21d-ba73e38b76a5", + "name": "Not Acceptable - Server cannot generate a response matching the Accept header", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Acceptable", + "code": 406, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "1cb3b833-da40-435b-a433-c0f568d6081d", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Content-Type is application/vnd.margo.manifest.v1+json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.manifest.v1+json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"required\":[\"manifestVersion\",\"bundle\",\"bundle.mediaType\",\"bundle.digest\",\"bundle.url\",\"deployments\"],\"properties\":{\"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.\\n\"},\"bundle\":{\"type\":[\"object\",\"null\"],\"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).\\n\",\"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.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable retrieval endpoint of the form /api/v1/clients/{clientId}/bundles/{digest} where {digest} equals bundle.digest.\\n\"}}},\"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\":{\"type\":\"object\",\"description\":\"Reference to a deployment manifest with content addressing and integrity verification.\\n\",\"required\":[\"deploymentId\",\"digest\",\"url\"],\"properties\":{\"deploymentId\":{\"type\":\"string\",\"description\":\"Unique identifier for the application deployment.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable endpoint of the form /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}. The {digest} MUST equal deployments[].digest; the referenced resource is immutable\\n\"}}}}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "1123ac51-ad1b-4723-b5f0-2e118d9bc603", + "name": "Retrieve an individual ApplicationDeployment YAML file", + "request": { + "name": "Retrieve an individual ApplicationDeployment YAML file", + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the Edge Compute Device", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier for the application deployment", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "deploymentId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.\n", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/yaml" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "c0a69212-66b0-4299-a03c-e8783aea1982", + "name": "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.\n", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "eu ut" + }, + { + "key": "Accept", + "value": "application/yaml" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/yaml" + }, + { + "disabled": true, + "description": { + "content": "application/yaml", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "ETag", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Accept-Encoding", + "type": "text/plain" + }, + "key": "Vary", + "value": "eu ut" + } + ], + "body": "pariatur deserun", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "d0220455-7b4f-4339-88cd-b0bff33254a4", + "name": "Deployment not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "eu ut" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "eu ut" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "49fca542-8984-43a0-8c28-e91ea946efde", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Content-Type is application/yaml\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/yaml\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "026934ca-82fc-40aa-8590-b76196bb4adb", + "name": "Report deployment status", + "request": { + "name": "Report deployment status", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "eu ut", + "key": "deploymentId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "ff63a1e6-a3fc-4c38-9f05-bcfaa1c59c37", + "name": "The deployment status was added, or updated, successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "OK", + "code": 200, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "52bf148a-4610-4f7c-851f-4350c5aaf239", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "aadf0152-6bc4-4911-9427-3d84296227f0", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "82b67493-2d36-4f91-89d3-dcafc3bbbd4b", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "fb34cf95-04d8-48a0-84a0-6f0ad4605614", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"consectetur sed\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"elit id consectetur\",\n \"status\": {\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"Ut exercitation\",\n \"source\": \"ad labore\",\n \"message\": \"Lore\"\n }\n },\n \"components\": [\n {\n \"name\": \"adipisicing sint aute in\",\n \"state\": \"installing\",\n \"error\": {\n \"code\": \"sit consequat\",\n \"source\": \"cillum id\",\n \"message\": \"incididunt consequat in minim\"\n }\n },\n {\n \"name\": \"enim\",\n \"state\": \"removed\",\n \"error\": {\n \"code\": \"labore nostrud\",\n \"source\": \"ad do commo\",\n \"message\": \"voluptate minim qui \"\n }\n }\n ],\n \"deviceId\": \"W7ya9asMOE/77yzT/vB/k/H5wRkDS/q/h.zNke9I/brJF0~0AUW-/udlPb46a/P\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "23460dd5-5021-4f77-a476-015cf46cd1db", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/deployments/:deploymentId/status - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + } + ], + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + }, + "event": [], + "variable": [ + { + "type": "any", + "value": "https://wfm.margo.org/", + "key": "baseUrl" + } + ], + "info": { + "_postman_id": "2a506b55-47f7-4ee0-87e2-4e976e3cd0f4", + "name": "Margo Workload Management API", + "version": { + "raw": "1.0.0-rc.2", + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": "rc,2", + "build": [], + "string": "1.0.0-rc.2" + }, + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": { + "content": "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.", + "type": "text/plain" + } + } +} \ No newline at end of file diff --git a/Data-Generator/wfm-supplier/postman_collection_functional.json b/Data-Generator/wfm-supplier/postman_collection_functional.json new file mode 100644 index 0000000..e8f6ba4 --- /dev/null +++ b/Data-Generator/wfm-supplier/postman_collection_functional.json @@ -0,0 +1,2395 @@ +{ + "_": { + "postman_id": "ca81b225-fab5-44b0-97d3-82588fc250e2" + }, + "item": [ + { + "id": "c006a5d9-d966-4b2c-b21f-e02a03bf5be5", + "name": "Download Root CA certificate", + "request": { + "name": "Download Root CA certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "GET", + "body": {} + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "462ffe48-2af8-46c2-9781-ccbfa0860d0c", + "name": "Root CA certificate", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding", + "certificate" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"certificate\": \"cupidatat\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "a5efd1c1-9806-4aac-9901-5d87b45424c1", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/onboarding/certificate - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/onboarding/certificate - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/onboarding/certificate - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"properties\":{\"certificate\":{\"type\":\"string\",\"description\":\"Base64-encoded certificate text\"}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/onboarding/certificate - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "87d8faa5-25fe-442b-bda0-2fc0ddf983b6", + "name": "Complete onboarding with client certificate", + "request": { + "name": "Complete onboarding with client certificate", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"ad sed deserunt\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"sunt in\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "e71e3fb8-62a3-4e2b-9511-0f8a3b52083e", + "name": "New client onboarded successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"ad sed deserunt\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"sunt in\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"clientId\": \"incididunt Ut quis in\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "1ff8dae9-06d3-486e-b156-5e2cd80e7a56", + "name": "Invalid certificate format or structure.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"ad sed deserunt\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"sunt in\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Invalid certificate\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "2dea28c5-00e4-4cab-b6e2-d199cea1cfe4", + "name": "Client certificate not trusted or client rejected.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "onboarding" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Accept", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"ad sed deserunt\",\n \"kind\": \"OnboardingRequest\",\n \"certificate\": \"sunt in\"\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": "{\n \"error\": \"Client rejected\"\n}", + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "342e096c-893c-4f76-b6d6-f0bbb1c2066f", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/onboarding - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[POST]::/api/v1/onboarding - Content-Type is application/json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[POST]::/api/v1/onboarding - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"properties\":{\"clientId\":{\"type\":\"string\"}},\"type\":\"object\"}\n\n// Validate if response matches JSON schema \npm.test(\"[POST]::/api/v1/onboarding - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "1f66d6e9-4a85-4ceb-a693-f1a43e5ca2c8", + "name": "Report device capabilities", + "request": { + "name": "Report device capabilities", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "ca621765-37e6-44b8-b846-9635b37bb1ba", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "9bed5895-ee56-417f-96c8-5d2fd3c7dd2d", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "8df9329e-5177-4d12-b05c-2bc81d63a76a", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "0b4b5451-41c9-4155-9724-e1a8fe863ca0", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "c37cb9e4-24a5-4106-bbbb-a48feaf4bee1", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "83aa0550-a4aa-451b-be6f-37600ab6a414", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "b560e49d-169f-40f7-b1ec-07620a7620a9", + "name": "Update device capabilities (Update)", + "request": { + "name": "Update device capabilities (Update)", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "cc86f6b1-287a-4e63-bbaa-147e162fb23f", + "name": "Capabilities reported successfully", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Created", + "code": 201, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "04562ab9-d47a-47c9-81c5-03301acae6bd", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "ed4a34b9-7c61-4289-885e-5b37cc02b01e", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "387af239-f4e4-429b-9584-90c414e0a7c4", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "f5bc7d9f-965f-4c6b-a4cb-398b3c1aff78", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "capabilities" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "PUT", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"veniam nisi in\",\n \"kind\": \"DeviceCapabilitiesManifest\",\n \"properties\": {\n \"id\": \"mollit\",\n \"vendor\": \"sit in velit\",\n \"modelNumber\": \"exercitation sit ex dolore\",\n \"serialNumber\": \"commodo tempor\",\n \"roles\": [\n \"Standalone Device\",\n \"Standalone Device\"\n ],\n \"resources\": {\n \"cpu\": {\n \"cores\": 48784956.717939556,\n \"architecture\": \"arm\"\n },\n \"memory\": \"fugiat incididunt esse sint labore\",\n \"storage\": \"enim irure ex fugiat culpa\",\n \"peripherals\": [\n {\n \"type\": \"camera\",\n \"manufacturer\": \"amet nulla deserunt exercitation elit\",\n \"model\": \"sint sit Duis\"\n },\n {\n \"type\": \"gpu\",\n \"manufacturer\": \"in Duis\",\n \"model\": \"fugiat magna aute aliquip\"\n }\n ],\n \"interfaces\": [\n {\n \"type\": \"ethernet\"\n },\n {\n \"type\": \"canbus\"\n }\n ]\n }\n }\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "a04696b2-7bff-4460-8d8d-b992f193b4db", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[PUT]::/api/v1/clients/:clientId/capabilities - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "1a5d47ce-5f1a-4f7a-ad56-061e87183fa6", + "name": "Retrieve bundle information for a specific device and digest", + "request": { + "name": "Retrieve bundle information for a specific device and digest", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the device-client", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "7392e234-6f45-43e2-a027-b0a86bad517e", + "name": "Bundle archive (immutable)", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.bundle.v1+tar+gzip" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "fugiat mollit velit" + } + ], + "body": "in se", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "045403b4-89ac-4c08-9146-7a92040c3476", + "name": "Representation not modified", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6ec4dc6e-ea73-4528-85e7-7880e7e9e816", + "name": "Invalid request.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "d3cae471-6d2e-4ef0-9569-6152f8d722ff", + "name": "Bundle not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "bundles", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Quoted ETag (same as digest) previously returned for this bundle.", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "5ffd6386-9b89-4bb4-8f4d-2ed8b85a381f", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/bundles/:digest - Content-Type is application/vnd.margo.bundle.v1+tar+gzip\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.bundle.v1+tar+gzip\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "7e655ed3-f370-463d-b506-630fb0defdbf", + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "request": { + "name": "Retrieve the complete desired state for all workloads assigned to a device", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) The unique identifier of the Edge Compute Device making the request", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "json" + }, + "id": "10811a89-c9bf-4b22-9e7e-9a34eb45a054", + "name": "Manifest returned in the negotiated format", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/vnd.margo.manifest.v1+json" + }, + { + "disabled": true, + "description": { + "content": "Format of the returned manifest", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "New ETag for the returned manifest", + "type": "text/plain" + }, + "key": "ETag", + "value": "fugiat mollit velit" + } + ], + "body": "{\n \"manifestVersion\": -53465074.990710005,\n \"bundle\": {\n \"mediaType\": \"Excepteur in anim laboris\",\n \"digest\": \"minim in Exc\",\n \"sizeBytes\": 19734530.933091983,\n \"url\": \"dolor aute\"\n },\n \"deployments\": [\n {\n \"deploymentId\": \"laborum deserunt eu\",\n \"digest\": \"r\",\n \"url\": \"mollit in\",\n \"sizeBytes\": 7914223.296396196\n },\n {\n \"deploymentId\": \"laboris Lorem minim laborum\",\n \"digest\": \"ut laborum ullamco est consectetur\",\n \"url\": \"nulla amet officia incididunt\",\n \"sizeBytes\": 18673697.001325935\n }\n ],\n \"bundle.mediaType\": 68572916.0651508,\n \"bundle.digest\": true,\n \"bundle.url\": \"amet do et\"\n}", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "3e26c5c6-ae6e-4abb-9012-84cb05939f62", + "name": "Not Modified - Manifest has not changed", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Modified", + "code": 304, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "55b7012f-aa47-4c20-903d-79c301ab8de9", + "name": "Not Acceptable - Server cannot generate a response matching the Accept header", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates which manifest formats the client supports. Supported values: application/vnd.margo.manifest.v1+json.\n", + "type": "text/plain" + }, + "key": "Accept", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Acceptable", + "code": 406, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "c2706fbd-e147-4a78-a04b-79c86c46387c", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Content-Type is application/vnd.margo.manifest.v1+json\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/vnd.margo.manifest.v1+json\");\n});\n", + "// Validate if response has JSON Body \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Response has JSON Body\", function () {\n pm.response.to.have.jsonBody();\n});\n", + "// Response Validation\nconst schema = {\"type\":\"object\",\"required\":[\"manifestVersion\",\"bundle\",\"bundle.mediaType\",\"bundle.digest\",\"bundle.url\",\"deployments\"],\"properties\":{\"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.\\n\"},\"bundle\":{\"type\":[\"object\",\"null\"],\"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).\\n\",\"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.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable retrieval endpoint of the form /api/v1/clients/{clientId}/bundles/{digest} where {digest} equals bundle.digest.\\n\"}}},\"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\":{\"type\":\"object\",\"description\":\"Reference to a deployment manifest with content addressing and integrity verification.\\n\",\"required\":[\"deploymentId\",\"digest\",\"url\"],\"properties\":{\"deploymentId\":{\"type\":\"string\",\"description\":\"The unique UUID from the ApplicationDeployment's metadata.annotations.id.\\n\"},\"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.\\n\"},\"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.\\n\"},\"url\":{\"type\":\"string\",\"description\":\"Content-addressable endpoint of the form /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}. The {digest} MUST equal deployments[].digest; the referenced resource is immutable\\n\"}}}}}}\n\n// Validate if response matches JSON schema \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments - Schema is valid\", function() {\n pm.response.to.have.jsonSchema(schema,{unknownFormats: [\"int32\", \"int64\", \"float\", \"double\"]});\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "7ccf9c54-36ea-42e2-b4fe-f6e00910c944", + "name": "Retrieve an individual ApplicationDeployment YAML file", + "request": { + "name": "Retrieve an individual ApplicationDeployment YAML file", + "description": { + "content": "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.\n", + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) Unique identifier of the Edge Compute Device", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) UUID of the ApplicationDeployment (metadata.annotations.id)", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "deploymentId" + }, + { + "disabled": false, + "description": { + "content": "(Required) 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.\n", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "digest" + } + ] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/yaml" + } + ], + "method": "GET", + "body": {}, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "469d2b44-34c0-4bba-ad20-4c7259c22031", + "name": "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.\n", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "fugiat mollit velit" + }, + { + "key": "Accept", + "value": "application/yaml" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "OK", + "code": 200, + "header": [ + { + "key": "Content-Type", + "value": "application/yaml" + }, + { + "disabled": true, + "description": { + "content": "application/yaml", + "type": "text/plain" + }, + "key": "Content-Type", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "ETag", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "public, max-age=31536000, immutable", + "type": "text/plain" + }, + "key": "Cache-Control", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Accept-Encoding", + "type": "text/plain" + }, + "key": "Vary", + "value": "fugiat mollit velit" + } + ], + "body": "esse dolor non ", + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "98f57b60-ffd9-4832-a944-0db7ce1ecede", + "name": "Deployment not found for the given digest", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + ":digest" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "disabled": true, + "description": { + "content": "Optional ETag for caching. The ETag is returned to the client from the /deployments endpoint, it is the digest of the state manifest.\n", + "type": "text/plain" + }, + "key": "If-None-Match", + "value": "fugiat mollit velit" + }, + { + "disabled": true, + "description": { + "content": "Indicates supported compression formats (e.g., gzip, br)", + "type": "text/plain" + }, + "key": "Accept-Encoding", + "value": "fugiat mollit velit" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "GET", + "body": {} + }, + "status": "Not Found", + "code": 404, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "8d5d19ed-a5c2-4216-8fd1-c50b05aadefe", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n", + "// Validate if response header has matching content-type\npm.test(\"[GET]::/api/v1/clients/:clientId/deployments/:deploymentId/:digest - Content-Type is application/yaml\", function () {\n pm.expect(pm.response.headers.get(\"Content-Type\")).to.include(\"application/yaml\");\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "5f847811-b779-4c72-ab6d-8e583b3950ac", + "name": "Report deployment status", + "request": { + "name": "Report deployment status", + "description": { + "type": "text/plain" + }, + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [ + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "clientId" + }, + { + "disabled": false, + "description": { + "content": "(Required) ", + "type": "text/plain" + }, + "type": "any", + "value": "fugiat mollit velit", + "key": "deploymentId" + } + ] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + }, + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + } + }, + "response": [ + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "c02c5cde-8707-45d1-b5b5-fb9238efb3ac", + "name": "The deployment status was added, or updated, successfully.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "OK", + "code": 200, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "aa4cfb2b-3d00-420b-a479-0c8ce289f2ec", + "name": "Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Bad Request", + "code": 400, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "6a805ce8-58f8-4845-81f6-fa3322bd8f9b", + "name": "Signature verification failed. Ensure you are signing with the correct X.509 private key.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unauthorized", + "code": 401, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "4934b7a1-d099-4702-afb6-9bb4681b4713", + "name": "Client certificate is not trusted or has been revoked.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Forbidden", + "code": 403, + "header": [], + "cookie": [] + }, + { + "_": { + "postman_previewlanguage": "text" + }, + "id": "92d987db-beaa-467c-97dd-059c18556681", + "name": "Request body includes a semantic error.", + "originalRequest": { + "url": { + "path": [ + "api", + "v1", + "clients", + ":clientId", + "deployments", + ":deploymentId", + "status" + ], + "host": [ + "{{baseUrl}}" + ], + "query": [], + "variable": [] + }, + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "X-Payload-Signature", + "value": "" + } + ], + "method": "POST", + "body": { + "mode": "raw", + "raw": "{\n \"apiVersion\": \"Ut voluptate\",\n \"kind\": \"DeploymentStatusManifest\",\n \"deploymentId\": \"cupidatat laboris nostrud\",\n \"status\": {\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"elit consequat labore quis\",\n \"message\": \"aliqua sunt sed\"\n }\n },\n \"components\": [\n {\n \"name\": \"eiusmod in\",\n \"state\": \"installed\",\n \"error\": {\n \"code\": \"eu nostrud dolore\",\n \"message\": \"con\"\n }\n },\n {\n \"name\": \"et ut\",\n \"state\": \"removing\",\n \"error\": {\n \"code\": \"est commodo\",\n \"message\": \"proident Lorem anim Ut laboris\"\n }\n }\n ]\n}", + "options": { + "raw": { + "headerFamily": "json", + "language": "json" + } + } + } + }, + "status": "Unprocessable Entity (WebDAV) (RFC 4918)", + "code": 422, + "header": [], + "cookie": [] + } + ], + "event": [ + { + "listen": "test", + "script": { + "id": "8ab3b05f-46c4-4c50-8104-8982f060f1ce", + "type": "text/javascript", + "exec": [ + "// Validate status 2xx \npm.test(\"[POST]::/api/v1/clients/:clientId/deployments/:deploymentId/status - Status code is 2xx\", function () {\n pm.response.to.be.success;\n});\n" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + } + ], + "auth": { + "type": "apikey", + "apikey": [ + { + "type": "any", + "value": "X-Payload-Signature", + "key": "key" + }, + { + "type": "any", + "value": "{{apiKey}}", + "key": "value" + }, + { + "type": "any", + "value": "header", + "key": "in" + } + ] + }, + "event": [], + "variable": [ + { + "type": "any", + "value": "https://wfm.margo.org/", + "key": "baseUrl" + } + ], + "info": { + "_postman_id": "ca81b225-fab5-44b0-97d3-82588fc250e2", + "name": "Margo Workload Management API", + "version": { + "raw": "1.0.0", + "major": 1, + "minor": 0, + "patch": 0, + "prerelease": [], + "build": [], + "string": "1.0.0" + }, + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "description": { + "content": "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.", + "type": "text/plain" + } + } +} \ No newline at end of file diff --git a/Runner/application-supplier/Hello World_04-08-2026_08-08-19.html b/Runner/application-supplier/Hello World_04-08-2026_08-08-19.html new file mode 100644 index 0000000..5b36a55 --- /dev/null +++ b/Runner/application-supplier/Hello World_04-08-2026_08-08-19.html @@ -0,0 +1,678 @@ + + + + + + +Application Supplier Conformance Test Report + + + + + + + +
+ +

+ Application Supplier Conformance Test Report +

+ +

+ Application: + Hello World +

+ +

+ Application Version: + 1.0 +

+ +

+ Generated: + 2026-08-04T08:08:19Z +

+ +
+ +
+ +

Summary

+ +

+ Total Checks: 22 + | + + ✅ Passed: 20 + + | + + ❌ Failed: 2 + +

+ +

+ + Success Rate: 90.9% + +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Application Description AttributeStatusTypeValidation Rule (Expected)Actual ValueRemarks
apiVersion + + +
+
FAIL
+ + + +
stringRequired (non-empty)(missing)API version is required but was not provided.
kind + + +
+
PASS
+ + + +
stringApplicationDescriptionApplicationDescriptionApplication type conforms to the required baseline.
id + + +
+
PASS
+ + + +
stringlowercase letters, numbers and dashes only, max length=200com-northstartida-hello-worldApplication identifier conforms to the required naming convention.
metadata.name + + +
+
PASS
+ + + +
stringRequired (non-empty)Hello WorldApplication name conforms to the required specification.
metadata.version + + +
+
PASS
+ + + +
stringRequired (non-empty)1.0Application version conforms to the required specification.
metadata.catalog.organization + + +
+
PASS
+ + + +
arrayAt least one organization1 organization(s)Organization information conforms to the required specification.
metadata.catalog.organization.name + + +
+
PASS
+ + + +
stringRequired (non-empty)Northstar Industrial ApplicationsOrganization information conforms to the required specification.
deploymentProfile + + +
+
PASS
+ + + +
arrayAt least one deployment profile1 deployment profile(s)Deployment profile configuration conforms to the required baseline.
deploymentProfile.type + + +
+
PASS
+ + + +
stringhelm | composehelmDeployment profile type conforms to the supported deployment specifications.
deploymentProfile.id + + +
+
PASS
+ + + +
stringRequired (non-empty)com-northstartida-hello-world-helm-aDeployment profile configuration conforms to the defined specification.
component.name + + +
+
PASS
+ + + +
stringRequired (non-empty)hello-worldComponent configuration conforms to the defined specification.
repository + + +
+
PASS
+ + + +
stringRepository URL requiredoci://northstarida.azurecr.io/charts/hello-worldRepository configuration conforms to the deployment requirements.
revision + + +
+
PASS
+ + + +
stringRequired (non-empty)1.0.1Revision information conforms to the deployment requirements.
schema + + +
+
PASS
+ + + +
stringname and dataType requiredrequireTextSchema 'requireText' conforms to the defined specification. Data type='string', AllowEmpty=false.
configuration.section + + +
+
PASS
+ + + +
stringRequired (non-empty)General SettingsConfiguration section has been successfully identified.
setting.parameter.greeting + + +
+
PASS
+ + + +
referenceMust match a parameter definitiongreetingParameter 'greeting' conforms to the defined specification.
setting.parameter.greeting.schema + + +
+
PASS
+ + + +
referenceMust match a schema definitionrequireTextSchema 'requireText' conforms to the defined specification.
setting.parameter.greetingAddressee + + +
+
PASS
+ + + +
referenceMust match a parameter definitiongreetingAddresseeParameter 'greetingAddressee' conforms to the defined specification.
setting.parameter.greetingAddressee.schema + + +
+
PASS
+ + + +
referenceMust match a schema definitionrequireTextSchema 'requireText' conforms to the defined specification.
parameter.greeting + + +
+
PASS
+ + + +
referenceMust match a deployment componenthello-worldParameter 'greeting' conforms to the defined component mapping requirements. Pointer='global.config.appGreeting'.
parameter.greetingAddressee + + +
+
PASS
+ + + +
referenceMust match a deployment componenthello-worldParameter 'greetingAddressee' conforms to the defined component mapping requirements. Pointer='global.config.appGreetingAddressee'.
Validating Helm component 'hello-world' + + +
+
FAIL
+ + + +
networkHelm repository reachableunreachableHelm validation failed for component 'hello-world' : oci unreachable: Error: invalid reference: invalid repository +
+ + + diff --git a/Runner/device-supplier/conformance-report-2026-06-30T04-43-20-000Z.html b/Runner/device-supplier/conformance-report-2026-06-30T04-43-20-000Z.html new file mode 100644 index 0000000..ea9b512 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-06-30T04-43-20-000Z.html @@ -0,0 +1,333 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

Margo Management Interface API 1.0.0

+

Generated: 2026-06-30T04:43:20Z

+
+
+

Summary

+

Total Tests: 43 | ✅ Passed: 43 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Report Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Role✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Onboard Device (Setup)✅ PASS201
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Report Deployment Status✅ PASS200
Onboard Device (Demo Setup)✅ PASS201
Invalid Capabilities (missing apiVersion) — expects 422 from assertion✅ PASS422
Get Root CA Certificate✅ PASS200
Onboard Trusted Device✅ PASS201
Reject Blocklisted Certificate✅ PASS403
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Onboard Without Signature Succeeds✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Current Deployments (Setup)✅ PASS200
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Reject Unsigned GET Deployments✅ PASS401
Reject Unsigned GET Bundle✅ PASS401
Reject Unsigned GET Deployment Manifest✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-06-30T04-51-30-000Z.html b/Runner/device-supplier/conformance-report-2026-06-30T04-51-30-000Z.html new file mode 100644 index 0000000..83ec7ce --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-06-30T04-51-30-000Z.html @@ -0,0 +1,333 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

Margo Management Interface API 1.0.0

+

Generated: 2026-06-30T04:51:30Z

+
+
+

Summary

+

Total Tests: 43 | ✅ Passed: 43 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Report Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Role✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Onboard Device (Setup)✅ PASS201
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Report Deployment Status✅ PASS200
Onboard Device (Demo Setup)✅ PASS201
Invalid Capabilities (missing apiVersion) — expects 422 from assertion✅ PASS422
Get Root CA Certificate✅ PASS200
Onboard Trusted Device✅ PASS201
Reject Blocklisted Certificate✅ PASS403
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Onboard Without Signature Succeeds✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Current Deployments (Setup)✅ PASS200
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Reject Unsigned GET Deployments✅ PASS401
Reject Unsigned GET Bundle✅ PASS401
Reject Unsigned GET Deployment Manifest✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-07-30T11-38-25-000Z.html b/Runner/device-supplier/conformance-report-2026-07-30T11-38-25-000Z.html new file mode 100644 index 0000000..99dba79 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-07-30T11-38-25-000Z.html @@ -0,0 +1,557 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

Margo Management Interface API 1.0.0

+

Generated: 2026-07-30T11:38:25Z

+
+
+

Summary

+

Total Tests: 75 | ✅ Passed: 63 | ❌ Failed: 12

+

Success Rate: 84.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities Without resources (now valid — regression test)✅ PASS201
Reject Capabilities When resources Present But Missing cpu✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Role✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Get Root CA Certificate✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)❌ FAIL404Expected HTTP 200, got 404
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)❌ FAIL404Expected HTTP 200, got 404
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Reset Desired State To Empty (test-control)❌ FAIL200Validation failed for field 'manifestVersion': equals
Get Deployments — Confirm Empty Desired State❌ FAIL200Validation failed for field 'manifestVersion': equals
Re-poll With Same ETag — Steady State (304, no reconciliation needed)❌ FAIL200Expected HTTP 304, got 200
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED❌ FAIL200Validation failed for field 'manifestVersion': equals
Get Deployments — Confirm Deployment Present, Version Advanced❌ FAIL200Validation failed for field 'manifestVersion': equals
Fetch Bundle For Newly-Added Deployment❌ FAIL404Expected HTTP 200, got 404
Fetch Individual Deployment Manifest❌ FAIL404Expected HTTP 200, got 404
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)❌ FAIL200Validation failed for field 'manifestVersion': equals
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only❌ FAIL200Validation failed for field 'manifestVersion': equals
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only❌ FAIL200Validation failed for field 'manifestVersion': equals
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-03T08-09-28-000Z.html b/Runner/device-supplier/conformance-report-2026-08-03T08-09-28-000Z.html new file mode 100644 index 0000000..4ef9a69 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-03T08-09-28-000Z.html @@ -0,0 +1,340 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

Margo Workload Management API 1.0.0

+

Generated: 2026-08-03T08:09:28Z

+
+
+

Summary

+

Total Tests: 44 | ✅ Passed: 43 | ❌ Failed: 1

+

Success Rate: 97.7%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Report Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Role✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Onboard Device (Setup)✅ PASS201
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Report Deployment Status✅ PASS200
Onboard Device (Demo Setup)✅ PASS201
Invalid Capabilities (missing apiVersion) — expects 422 from assertion✅ PASS422
Invalid Memory Format❌ FAIL201Expected HTTP 422, got 201
Get Root CA Certificate✅ PASS200
Onboard Trusted Device✅ PASS201
Reject Blocklisted Certificate✅ PASS403
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Onboard Without Signature Succeeds✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Current Deployments (Setup)✅ PASS200
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Reject Unsigned GET Deployments✅ PASS401
Reject Unsigned GET Bundle✅ PASS401
Reject Unsigned GET Deployment Manifest✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-04T08-46-12-000Z.html b/Runner/device-supplier/conformance-report-2026-08-04T08-46-12-000Z.html new file mode 100644 index 0000000..dd50d62 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-04T08-46-12-000Z.html @@ -0,0 +1,557 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

Margo Workload Management API 1.0.0

+

Generated: 2026-08-04T08:46:12Z

+
+
+

Summary

+

Total Tests: 75 | ✅ Passed: 75 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
Get Root CA Certificate✅ PASS200
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Confirm Empty Desired State✅ PASS200
Re-poll With Same ETag — Steady State (304, no reconciliation needed)✅ PASS304
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED✅ PASS200
Get Deployments — Confirm Deployment Present, Version Advanced✅ PASS200
Fetch Bundle For Newly-Added Deployment✅ PASS200
Fetch Individual Deployment Manifest✅ PASS200
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)✅ PASS200
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only✅ PASS200
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities Without resources (now valid — regression test)✅ PASS201
Reject Capabilities When resources Present But Missing cpu✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Role✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)✅ PASS200
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)✅ PASS200
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-42-43-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-42-43-000Z.html new file mode 100644 index 0000000..b0f2c3d --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-42-43-000Z.html @@ -0,0 +1,342 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:42:43Z

+
+
+

Summary

+

Total Tests: 44 | ✅ Passed: 44 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Report Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Onboard Device (Setup)✅ PASS201
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Report Deployment Status✅ PASS200
Onboard Device (Demo Setup)✅ PASS201
Invalid Capabilities (missing apiVersion) — expects 422 from assertion✅ PASS422
Non-Standard Memory String Is Accepted (spec places no format constraint on memory/storage)✅ PASS201
Get Root CA Certificate✅ PASS200
Onboard Trusted Device✅ PASS201
Reject Blocklisted Certificate✅ PASS403
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Onboard Without Signature Succeeds✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Current Deployments (Setup)✅ PASS200
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Reject Unsigned GET Deployments✅ PASS401
Reject Unsigned GET Bundle✅ PASS401
Reject Unsigned GET Deployment Manifest✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-42-55-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-42-55-000Z.html new file mode 100644 index 0000000..efa12c3 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-42-55-000Z.html @@ -0,0 +1,566 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:42:55Z

+
+
+

Summary

+

Total Tests: 76 | ✅ Passed: 76 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Get Root CA Certificate✅ PASS200
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities With Empty Peripherals (regression test)✅ PASS201
Reject Capabilities Missing cpus✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Onboard Dedicated Client For This Scenario (not shared)✅ PASS201
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Confirm Empty Desired State✅ PASS200
Re-poll With Same ETag — Steady State (304, no reconciliation needed)✅ PASS304
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED✅ PASS200
Get Deployments — Confirm Deployment Present, Version Advanced✅ PASS200
Fetch Bundle For Newly-Added Deployment✅ PASS200
Fetch Individual Deployment Manifest✅ PASS200
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)✅ PASS200
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only✅ PASS200
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)✅ PASS200
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)✅ PASS200
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-42-59-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-42-59-000Z.html new file mode 100644 index 0000000..8ccadf6 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-42-59-000Z.html @@ -0,0 +1,566 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:42:59Z

+
+
+

Summary

+

Total Tests: 76 | ✅ Passed: 76 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities With Empty Peripherals (regression test)✅ PASS201
Reject Capabilities Missing cpus✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)✅ PASS200
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)✅ PASS200
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Get Root CA Certificate✅ PASS200
Onboard Dedicated Client For This Scenario (not shared)✅ PASS201
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Confirm Empty Desired State✅ PASS200
Re-poll With Same ETag — Steady State (304, no reconciliation needed)✅ PASS304
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED✅ PASS200
Get Deployments — Confirm Deployment Present, Version Advanced✅ PASS200
Fetch Bundle For Newly-Added Deployment✅ PASS200
Fetch Individual Deployment Manifest✅ PASS200
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)✅ PASS200
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only✅ PASS200
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-43-03-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-43-03-000Z.html new file mode 100644 index 0000000..db09323 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-43-03-000Z.html @@ -0,0 +1,566 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:43:03Z

+
+
+

Summary

+

Total Tests: 76 | ✅ Passed: 76 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities With Empty Peripherals (regression test)✅ PASS201
Reject Capabilities Missing cpus✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Get Root CA Certificate✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Onboard Dedicated Client For This Scenario (not shared)✅ PASS201
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Confirm Empty Desired State✅ PASS200
Re-poll With Same ETag — Steady State (304, no reconciliation needed)✅ PASS304
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED✅ PASS200
Get Deployments — Confirm Deployment Present, Version Advanced✅ PASS200
Fetch Bundle For Newly-Added Deployment✅ PASS200
Fetch Individual Deployment Manifest✅ PASS200
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)✅ PASS200
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only✅ PASS200
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)✅ PASS200
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)✅ PASS200
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-43-47-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-43-47-000Z.html new file mode 100644 index 0000000..6e1dfa9 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-43-47-000Z.html @@ -0,0 +1,125 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: unknown

+

Generated: 2026-08-17T08:43:47Z

+
+
+

Summary

+

Total Tests: 13 | ✅ Passed: 13 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Get Root CA Certificate✅ PASS200
Onboard Device✅ PASS201
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Update Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Deployment Manifest✅ PASS200
Get Deployments — Cached (ETag match returns 304)✅ PASS304
Download Deployment Bundle✅ PASS200
Report Deployment Status✅ PASS200
Onboard Device (Setup)✅ PASS201
Reject Invalid Peripheral Type in Capabilities✅ PASS422
Reject Unsigned Capabilities Request✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-44-44-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-44-44-000Z.html new file mode 100644 index 0000000..853ce45 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-44-44-000Z.html @@ -0,0 +1,342 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:44:44Z

+
+
+

Summary

+

Total Tests: 44 | ✅ Passed: 44 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities with POST✅ PASS201
Report Capabilities with PUT✅ PASS201
Onboard Device (Setup)✅ PASS201
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Onboard Device (Setup)✅ PASS201
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Report Deployment Status✅ PASS200
Onboard Device (Demo Setup)✅ PASS201
Invalid Capabilities (missing apiVersion) — expects 422 from assertion✅ PASS422
Non-Standard Memory String Is Accepted (spec places no format constraint on memory/storage)✅ PASS201
Get Root CA Certificate✅ PASS200
Onboard Trusted Device✅ PASS201
Reject Blocklisted Certificate✅ PASS403
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Onboard Without Signature Succeeds✅ PASS201
Onboard Device (Setup)✅ PASS201
Get Current Deployments (Setup)✅ PASS200
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Reject Unsigned GET Deployments✅ PASS401
Reject Unsigned GET Bundle✅ PASS401
Reject Unsigned GET Deployment Manifest✅ PASS401
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T08-44-48-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T08-44-48-000Z.html new file mode 100644 index 0000000..f0bfef2 --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T08-44-48-000Z.html @@ -0,0 +1,566 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T08:44:48Z

+
+
+

Summary

+

Total Tests: 76 | ✅ Passed: 76 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Reject Onboarding With Invalid Api Version✅ PASS400
Reject Onboarding With Missing Certificate✅ PASS400
Reject Onboarding With Empty Certificate✅ PASS400
Reject Onboarding With Missing Kind✅ PASS400
Reject Onboarding With Wrong Kind Value✅ PASS400
Reject Blocklisted Certificate✅ PASS403
Onboard Without Signature Succeeds (alt clientId, not shared)✅ PASS201
Onboard Trusted Device (canonical, shared clientId — must stay last)✅ PASS201
Report Capabilities with POST (full resources)✅ PASS201
Report Capabilities with PUT (full resources)✅ PASS201
Report Capabilities With Empty Peripherals (regression test)✅ PASS201
Reject Capabilities Missing cpus✅ PASS422
Reject Capabilities With Missing Properties✅ PASS422
Reject Capabilities With Invalid Peripheral Type✅ PASS422
Reject Capabilities With Invalid Interface Type✅ PASS422
Reject Capabilities With Invalid Cpu Architecture✅ PASS422
Reject Capabilities With Missing Content-Digest✅ PASS400
Reject Capabilities Without Signature✅ PASS401
Reject Capabilities For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Report Deployment Status✅ PASS200
Report Deployment Status With Optional deviceId (now type-checked)✅ PASS200
Reject Status With Invalid State✅ PASS422
Reject Status With Missing Component Name✅ PASS422
Reject Status With Path Deployment Mismatch✅ PASS422
Reject Status With Missing Content-Digest✅ PASS400
Reject Status Without Signature✅ PASS401
Get Current Deployments✅ PASS200
Get Deployments With Matching ETag✅ PASS304
Reject Deployments Request With Unsupported Accept Header✅ PASS406
Reject Unsigned GET Deployments✅ PASS401
Reject Deployments For Unknown Client✅ PASS404
Get Current Deployments (local setup)✅ PASS200
Download Individual Deployment Manifest✅ PASS200
Download Individual Deployment Manifest With Matching ETag✅ PASS304
Reject Deployment Manifest Download With Wrong Digest✅ PASS404
Reject Unsigned GET Deployment Manifest✅ PASS401
Get Root CA Certificate✅ PASS200
Get Current Deployments (local setup)✅ PASS200
Download Deployment Bundle✅ PASS200
Download Bundle With Matching ETag✅ PASS304
Reject Bundle Download With Wrong Digest✅ PASS404
Reject Unsigned GET Bundle✅ PASS401
Onboard Dedicated Client For This Scenario (not shared)✅ PASS201
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Confirm Empty Desired State✅ PASS200
Re-poll With Same ETag — Steady State (304, no reconciliation needed)✅ PASS304
Add Default Deployment Back (test-control) — DESIRED-STATE-ADDED✅ PASS200
Get Deployments — Confirm Deployment Present, Version Advanced✅ PASS200
Fetch Bundle For Newly-Added Deployment✅ PASS200
Fetch Individual Deployment Manifest✅ PASS200
Report Status: pending✅ PASS200
Report Status: installing✅ PASS200
Report Status: installed✅ PASS200
Assign A Second Deployment (test-control)✅ PASS200
Report Status: installed (second deployment)✅ PASS200
Unassign Second Deployment (test-control) — back to default only✅ PASS200
Report Status: removed (second deployment, no longer desired)✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
Assign Both Sample Apps (test-control)✅ PASS200
Get Deployments — Confirm Mock Server Reports Both Apps✅ PASS200
Fetch App A Deployment Manifest (nginx compose)✅ PASS200
Fetch App A's Actual compose.yaml (served by this mock server)✅ PASS200
Report App A Status: pending✅ PASS200
Report App A Status: installing✅ PASS200
Report App A Status: installed✅ PASS200
Fetch App B Deployment Manifest (redis compose)✅ PASS200
Fetch App B's Actual compose.yaml (served by this mock server)✅ PASS200
Report App B Status: pending✅ PASS200
Report App B Status: installing✅ PASS200
Report App B Status: installed — both apps now running✅ PASS200
Remove App B, Keep App A (test-control)✅ PASS200
Get Deployments — Confirm Exactly App A Remains✅ PASS200
Report App B Status: removed (no longer desired)✅ PASS200
Restore Default Deployment (test-control) — leave shared client in the state siblings expect✅ PASS200
Get Deployments — Confirm Restored To Default Only✅ PASS200
+ + diff --git a/Runner/device-supplier/conformance-report-2026-08-17T12-52-09-000Z.html b/Runner/device-supplier/conformance-report-2026-08-17T12-52-09-000Z.html new file mode 100644 index 0000000..eb1cd2a --- /dev/null +++ b/Runner/device-supplier/conformance-report-2026-08-17T12-52-09-000Z.html @@ -0,0 +1,104 @@ + + + + Device Supplier Conformance Report + + + +
+

Device Supplier Conformance Test Report

+

CTT Margo Version: 1.0.0-rc.2

+

Claimed App Version: 1.0.0-rc.2

+

Generated: 2026-08-17T12:52:09Z

+
+
+

Summary

+

Total Tests: 10 | ✅ Passed: 10 | ❌ Failed: 0

+

Success Rate: 100.0%

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepStatusHTTP CodeDetails
Onboard Device (Setup)✅ PASS201
Report Capabilities — Standalone Device Role (compose only)✅ PASS201
Report Capabilities — Standalone Cluster Role (helm only)✅ PASS201
Reject Capabilities — Invalid supportedDeploymentTypes Value✅ PASS422
Reject Capabilities — Invalid supportedRuntimes Value✅ PASS422
Reject Capabilities — cpus[] Entry Missing Required cores✅ PASS422
Onboard Device (Setup)✅ PASS201
Get Deployments With No Accept Header — Defaults To Manifest Format✅ PASS200
Reset Desired State To Empty (test-control)✅ PASS200
Get Deployments — Zero Deployments Still Returns A Valid (Empty) Manifest✅ PASS200
+ + diff --git a/Runner/device-supplier/test-execution.log b/Runner/device-supplier/test-execution.log new file mode 100644 index 0000000..6c25148 --- /dev/null +++ b/Runner/device-supplier/test-execution.log @@ -0,0 +1,45 @@ + +╔══════════════════════════════════════════════════════════════════════════════╗ +║ Device Supplier Conformance Test Runner ║ +║ Data-Driven Test Framework ║ +║ ║ +║ Testing against: https://localhost:3001/v1alpha2/margo ║ +║ Spec: Margo Management Interface API 1.0.0-rc.2 ║ +╚══════════════════════════════════════════════════════════════════════════════╝ + +Claimed App Version: 1.0.0-rc.2 · CTT Margo Version: 1.0.0-rc.2 +✅ WFM Server is ready + +▶ Running Scenario: Capability Reporting — Device Role Variants (device-core-capability-roles) + Description: Per docs.margo.org/specification/margo-management-interface/device-capabilities and the Device Supplier conformance requirements, a device fills either the Standalone Cluster role (Kubernetes + Helm) or the Standalone Device role (Compose) — supportedDeploymentTypes is how a device declares which. This scenario covers both role variants as positive cases, plus negative coverage for invalid enum values and a malformed cpus[] entry not exercised by other groups. + → Step: Onboard Device (Setup) + 📎 Captured clientId = 8950bc84-01c3-475a-922b-8804a9885dec + 📎 Captured deviceId = 8950bc84-01c3-475a-922b-8804a9885dec + ✅ PASS - HTTP 201 (Expected: 201) + → Step: Report Capabilities — Standalone Device Role (compose only) + ✅ PASS - HTTP 201 (Expected: 201) + → Step: Report Capabilities — Standalone Cluster Role (helm only) + ✅ PASS - HTTP 201 (Expected: 201) + → Step: Reject Capabilities — Invalid supportedDeploymentTypes Value + ✅ PASS - HTTP 422 (Expected: 422) + → Step: Reject Capabilities — Invalid supportedRuntimes Value + ✅ PASS - HTTP 422 (Expected: 422) + → Step: Reject Capabilities — cpus[] Entry Missing Required cores + ✅ PASS - HTTP 422 (Expected: 422) + +▶ Running Scenario: Desired State — Default Negotiation and Zero-Deployment Manifest (device-core-manifest-semantics) + Description: Per docs.margo.org/specification/margo-management-interface/desired-state: (1) the WFM (here, our mock server) MUST default to application/vnd.margo.manifest.v1+json when the Accept header is omitted entirely, not just when it's the exact expected value; (2) when a client has zero deployments assigned, the manifest's deployments field MUST still be a valid (empty) array. Both are edge cases the other device-supplier groups don't exercise directly. Note: the spec also requires the manifest's bundle field to be explicit null (not omitted) when deployments is empty — not independently verified here, because this suite's validation engine can't distinguish a field that's present-but-null from one that's absent (both read as Go/JS nil); confirmed instead by reading the mock server's response-construction code directly. + → Step: Onboard Device (Setup) + 📎 Captured clientId = c5c47934-1f99-43a4-8b5e-137d7bb7e6b2 + ✅ PASS - HTTP 201 (Expected: 201) + → Step: Get Deployments With No Accept Header — Defaults To Manifest Format + ✅ PASS - HTTP 200 (Expected: 200) + → Step: Reset Desired State To Empty (test-control) + ✅ PASS - HTTP 200 (Expected: 200) + → Step: Get Deployments — Zero Deployments Still Returns A Valid (Empty) Manifest + ✅ PASS - HTTP 200 (Expected: 200) + +╔══════════════════════════════════════════════════════════════════════════════╗ +║ Test Results: 10 PASSED, 0 FAILED (Total: 10) +╚══════════════════════════════════════════════════════════════════════════════╝ +📊 Test report saved: reports/conformance-report-2026-08-17T12-52-09-000Z.html diff --git a/Runner/margo-test-run.sh b/Runner/margo-test-run.sh new file mode 100755 index 0000000..882cf22 --- /dev/null +++ b/Runner/margo-test-run.sh @@ -0,0 +1,310 @@ +#!/usr/bin/env bash + +################################################################################ +# MARGO Test Case Runner - Runner CLI +################################################################################ +# Purpose: Execute conformance test cases for MARGO personas +# Personas: WFM Supplier, Device Supplier +# +# For WFM Supplier: Runs Newman against postman_collection.json +# For Device Supplier: Runs device supplier conformance tests +################################################################################ + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFORMANCE_DIR="$(cd "$ROOT_DIR/.." && pwd)" +WFM_DIR="$CONFORMANCE_DIR/wfm-supplier" +DEVICE_DIR="$CONFORMANCE_DIR/device-supplier" +DATA_GEN_DIR="$CONFORMANCE_DIR/Data-Generator" +RUNNER_DIR="$ROOT_DIR" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# ============================================ +# Utility Functions +# ============================================ +log() { + echo -e "${BLUE}[$(date +'%Y-%m-%d %H:%M:%S')]${NC} $*" +} + +success() { + echo -e "${GREEN}✅ $*${NC}" +} + +error() { + echo -e "${RED}❌ $*${NC}" + exit 1 +} + +warning() { + echo -e "${YELLOW}⚠️ $*${NC}" +} + +# ============================================ +# WFM Supplier - Execute tests via Newman +# ============================================ +wfm_run() { + log "🚀 Running WFM Supplier conformance tests via Newman..." + + # Ensure output directories exist + mkdir -p "$RUNNER_DIR/wfm-supplier" + mkdir -p "$WFM_DIR" + + # Check if tests were generated (in Data-Generator folder) + if [[ -f "$DATA_GEN_DIR/wfm-supplier/postman_collection.json" ]]; then + log "📋 Found generated tests in Data-Generator, preparing for execution..." + # Copy from Data-Generator to wfm-supplier for Newman to use + cp "$DATA_GEN_DIR/wfm-supplier/postman_collection.json" "$WFM_DIR/" || error "Failed to copy postman_collection.json" + + # Copy newman data if it exists + if [[ -d "$DATA_GEN_DIR/wfm-supplier/newman-data" ]]; then + cp -r "$DATA_GEN_DIR/wfm-supplier/newman-data" "$WFM_DIR/" 2>/dev/null || true + fi + success "✅ Tests copied from Data-Generator" + elif [[ ! -f "$WFM_DIR/postman_collection.json" ]]; then + error "❌ postman_collection.json not found! + +To fix this, first generate the tests: + cd conformance/Data-Generator + ./margo-test-gen.sh wfm https://symphony.machine:8082/v1alpha2/margo + +Then run tests: + cd ../Runner + ./margo-test-run.sh wfm" + fi + + # Run Newman + (cd "$WFM_DIR" && bash 2-run_newman.sh) || error "Newman test execution failed" + + # Copy reports to Runner directory + if ls "$WFM_DIR"/report_*.html 1>/dev/null 2>&1; then + cp "$WFM_DIR"/report_*.html "$RUNNER_DIR/wfm-supplier/" 2>/dev/null || true + log "📊 Reports saved to: $RUNNER_DIR/wfm-supplier/" + fi + + success "WFM Supplier tests completed" + + # Display device status if available + if [[ -f "$WFM_DIR/newman-data/device-agent.env.json" ]]; then + log "📋 Device Status from API tests:" + cat "$WFM_DIR/newman-data/device-agent.env.json" | grep -E "clientId|vendor|model|cpu|memory|deployment" || true + fi +} + +# ============================================ +# Device Supplier - Execute tests +# ============================================ +device_run() { + log "🚀 Running Device Supplier conformance tests..." + + # Ensure output directory exists + mkdir -p "$RUNNER_DIR/device-supplier" + + # Build and run tests + (cd "$DEVICE_DIR" && make run-tests) || error "Device supplier tests failed" + + # Copy reports to Runner directory + if [[ -d "$DEVICE_DIR/reports" ]]; then + if ls "$DEVICE_DIR/reports"/*.html 1>/dev/null 2>&1; then + cp "$DEVICE_DIR/reports"/*.html "$RUNNER_DIR/device-supplier/" 2>/dev/null || true + log "📊 Reports saved to: $RUNNER_DIR/device-supplier/" + fi + fi + + success "Device Supplier tests completed" +} + +# ============================================ +# Device Supplier - Execute workloads (3-execute-workloads) +# ============================================ +device_execute_workloads() { + log "🚀 Executing Device Supplier workloads (deployment phase)..." + + # Ensure output directory exists + mkdir -p "$RUNNER_DIR/device-supplier" + + # Execute workloads phase + (cd "$WFM_DIR" && bash 3-execute-workloads.sh) || error "Workload execution failed" + + success "Device Supplier workload execution completed" +} + +# ============================================ +# Device Supplier - Full demo (build, start, run tests, cleanup) +# ============================================ +device_demo() { + log "🎬 Running Device Supplier full demo..." + + # Ensure output directory exists + mkdir -p "$RUNNER_DIR/device-supplier" + + (cd "$DEVICE_DIR" && make demo) || error "Device supplier demo failed" + + success "Device Supplier demo completed" +} + +# ============================================ +# Full end-to-end workflow +# ============================================ +full_workflow() { + log "🔄 Starting full conformance workflow (WFM + Device)..." + + log "Step 1: Running WFM tests..." + wfm_run + + log "" + log "Step 2: Running Device tests..." + device_run + + log "" + log "Step 3: Executing workloads..." + device_execute_workloads + + success "🎉 Full workflow completed!" +} + +# ============================================ +# Show usage +# ============================================ +usage() { + cat <<'EOF' +MARGO Test Case Runner (Runner CLI) + +Usage: + ./margo-test-run.sh [PERSONA] [COMMAND] + +Personas: + 1, wfm Run WFM Supplier conformance tests + 2, device Run Device Supplier conformance tests + all Run WFM + Device + Workload execution (full workflow) + interactive Interactive menu (default) + +Device Commands (optional): + tests Run device tests only + demo Full demo (build, start server, run tests) + workloads Execute workload deployment phase + cleanup Stop device server and clean + +Examples: + ./margo-test-run.sh wfm + ./margo-test-run.sh device tests + ./margo-test-run.sh device demo + ./margo-test-run.sh all + ./margo-test-run.sh interactive + ./margo-test-run.sh (runs interactive mode) + +Output Locations: + WFM: ./Runner/wfm-supplier/report_*.html + Device: ./Runner/device-supplier/report_*.html + +EOF +} + +# ============================================ +# Interactive Menu +# ============================================ +interactive_menu() { + while true; do + clear + echo "======================================================================" + echo " MARGO Test Case Runner (Runner CLI)" + echo "======================================================================" + echo "" + echo "Select Persona:" + echo " 1. WFM Supplier - Run API contract tests" + echo " 2. Device Supplier - Run conformance tests" + echo " 3. Device Demo - Full demo workflow" + echo " 4. Full Workflow - WFM + Device + Workloads" + echo " 5. Exit" + echo "" + read -p "Enter choice (1-5): " choice + + case "$choice" in + 1|wfm) + wfm_run + read -p "Press Enter to continue..." _ + ;; + 2|device) + device_run + read -p "Press Enter to continue..." _ + ;; + 3|demo) + device_demo + read -p "Press Enter to continue..." _ + ;; + 4|workflow|all) + full_workflow + read -p "Press Enter to continue..." _ + ;; + 5|exit) + log "Exiting..." + exit 0 + ;; + *) + error "Invalid choice" + ;; + esac + done +} + +# ============================================ +# Main +# ============================================ +main() { + local persona="${1:-}" + local cmd="${2:-}" + + # Interactive mode if no arguments + if [[ -z "$persona" ]]; then + interactive_menu + return 0 + fi + + case "$persona" in + 1|wfm) + wfm_run + ;; + 2|device) + case "$cmd" in + tests) + device_run + ;; + demo) + device_demo + ;; + workloads) + device_execute_workloads + ;; + cleanup) + (cd "$DEVICE_DIR" && make kill-server && make clean) + ;; + *) + device_run # default + ;; + esac + ;; + 3|demo) + device_demo + ;; + all|workflow) + full_workflow + ;; + interactive) + interactive_menu + ;; + help|--help|-h) + usage + ;; + *) + error "Unknown persona: $persona" + ;; + esac +} + +main "$@" diff --git a/Runner/wfm-supplier/wfm-scenario-report-core_20260817_125217.html b/Runner/wfm-supplier/wfm-scenario-report-core_20260817_125217.html new file mode 100644 index 0000000..bb2242d --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-core_20260817_125217.html @@ -0,0 +1,153 @@ + + + + + WFM Conformance Report — core + + + +

Margo WFM Conformance Report

+
+ Group: core  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T12:52:17.673Z +
+ +
+ ❌ 4 passed, 3 failed, 7 total +
+ +

Scenario Summary

+ + + + + + + + + + + + + + + + + + +
ScenarioTotalPassedFailed
Capability Reporting — Device Role Variants532
Desired State — Default Content Negotiation211
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSCapability Reporting — Device Role Variantsstep-wfm-core-1.0Onboard Device (Setup)POST/api/v1/onboarding201201
PASSCapability Reporting — Device Role Variantsstep-wfm-core-1.1Report Capabilities — Standalone Device Role (compose only)POST/api/v1/clients/client-c541f8ab0c840a26-1786971137/capabilities/client-c541f8ab0c840a26-1786971137201201
PASSCapability Reporting — Device Role Variantsstep-wfm-core-1.2Report Capabilities — Standalone Cluster Role (helm only)POST/api/v1/clients/client-c541f8ab0c840a26-1786971137/capabilities/client-c541f8ab0c840a26-1786971137201201
FAILCapability Reporting — Device Role Variantsstep-wfm-core-1.3Reject Capabilities — Invalid supportedDeploymentTypes ValuePOST/api/v1/clients/client-c541f8ab0c840a26-1786971137/capabilities/client-c541f8ab0c840a26-1786971137422201expected HTTP 422, got 201
FAILCapability Reporting — Device Role Variantsstep-wfm-core-1.4Reject Capabilities — Invalid supportedRuntimes ValuePOST/api/v1/clients/client-c541f8ab0c840a26-1786971137/capabilities/client-c541f8ab0c840a26-1786971137422201expected HTTP 422, got 201
PASSDesired State — Default Content Negotiationstep-wfm-core-2.0Onboard Device (Setup)POST/api/v1/onboarding201201
FAILDesired State — Default Content Negotiationstep-wfm-core-2.1Get Deployments With No Accept Header — Defaults To Manifest FormatGET/api/v1/clients/client-2b3cf9c3f17a3f05-1786971137/deployments200500expected HTTP 200, got 500
+ + \ No newline at end of file diff --git a/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083730.html b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083730.html new file mode 100644 index 0000000..7c09505 --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083730.html @@ -0,0 +1,399 @@ + + + + + WFM Conformance Report — silver + + + +

Margo WFM Conformance Report

+
+ Group: silver  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T08:37:31.825Z +
+ +
+ ❌ 11 passed, 17 failed, 28 total +
+ +

Scenario Summary

+ + + + + + + + + + + +
ScenarioTotalPassedFailed
Margo Workload Management API281117
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSMargo Workload Management APIc42f4b7d-992a-4af0-924b-2eb4d787678aDownload Root CA certificate — Root CA certificateGET/api/v1/onboarding/certificate200200
PASSMargo Workload Management API0b95ee4e-dc64-4119-b07e-69c3342da26aComplete onboarding with client certificate — New client onboarded successfully.POST/api/v1/onboarding201201
PASSMargo Workload Management API0510e725-a124-415f-a9b9-0d369e1d94e2Report device capabilities — Capabilities reported successfullyPOST/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850201201
PASSMargo Workload Management API8bb41ecf-4010-4dd0-ba9e-11033cfe66cdUpdate device capabilities (Update) — Capabilities reported successfullyPUT/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850201201
PASSMargo Workload Management API195c5f23-c8c7-491a-b622-3ce29a0aa9c4Retrieve bundle information for a specific device and digest — Bundle archive (immutable)GET/api/v1/clients/client-f76a9a593484a08f-1786955850/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API2bd8b6a4-ac94-435b-a365-42f07a064bc3Retrieve the complete desired state for all workloads assigned to a device — Manifest returned in the negotiated formatGET/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments200200
PASSMargo Workload Management API36fdd629-6c79-4991-86a2-49be8dbcf96fRetrieve an individual ApplicationDeployment YAML file — 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. +GET/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0Report deployment status — The deployment status was added, or updated, successfully.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/status200400
FAILMargo Workload Management APIf9e10c20-8474-47ec-81c0-fc7c0823891dComplete onboarding with client certificate — Invalid certificate format or structure.POST/api/v1/onboarding400201expected HTTP 400, got 201
FAILMargo Workload Management APIe89bca4b-f257-434a-8397-d604c2b42eb8Complete onboarding with client certificate — Client certificate not trusted or client rejected.POST/api/v1/onboarding403201expected HTTP 403, got 201
FAILMargo Workload Management APIf206fb46-f592-45ea-a6f1-6569371ee515Report device capabilities — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850400201expected HTTP 400, got 201
FAILMargo Workload Management API5fc47546-2c1a-4956-9b6a-cfdfb31b88f6Report device capabilities — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850401400expected HTTP 401, got 400
FAILMargo Workload Management API066c0155-a489-428e-9535-dabb36c7aaf6Report device capabilities — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850403400expected HTTP 403, got 400
FAILMargo Workload Management APIa3f7146c-5c7f-41f1-82d4-9ed75c84ec24Report device capabilities — Request body includes a semantic error.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850422400expected HTTP 422, got 400
FAILMargo Workload Management APIeb9e178c-5df0-420c-8169-c223cc174a86Update device capabilities (Update) — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.PUT/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850400201expected HTTP 400, got 201
FAILMargo Workload Management API7b600483-4a8d-41ea-957c-88600e2a5f83Update device capabilities (Update) — Signature verification failed. Ensure you are signing with the correct X.509 private key.PUT/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850401400expected HTTP 401, got 400
FAILMargo Workload Management API6fb8f5bb-2932-4287-adb3-4e2f0b477a90Update device capabilities (Update) — Client certificate is not trusted or has been revoked.PUT/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850403400expected HTTP 403, got 400
FAILMargo Workload Management API8ec05b96-3f1d-4030-b2c6-67c9e98bf811Update device capabilities (Update) — Request body includes a semantic error.PUT/api/v1/clients/client-f76a9a593484a08f-1786955850/capabilities/client-f76a9a593484a08f-1786955850422400expected HTTP 422, got 400
FAILMargo Workload Management API5755e4a7-8329-4ceb-b210-8c41e6423569Retrieve bundle information for a specific device and digest — Representation not modifiedGET/api/v1/clients/client-f76a9a593484a08f-1786955850/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000304404expected HTTP 304, got 404
FAILMargo Workload Management APIa7d2c754-66c3-4e45-aecb-987e481d9343Retrieve bundle information for a specific device and digest — Invalid request.GET/api/v1/clients/client-f76a9a593484a08f-1786955850/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000400404expected HTTP 400, got 404
PASSMargo Workload Management API80315591-d033-4c57-8d63-9979889e6317Retrieve bundle information for a specific device and digest — Bundle not found for the given digestGET/api/v1/clients/client-f76a9a593484a08f-1786955850/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
FAILMargo Workload Management API17a2b787-ca67-4dd6-a72b-27cd1290bebcRetrieve the complete desired state for all workloads assigned to a device — Not Modified - Manifest has not changedGET/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments304200expected HTTP 304, got 200
FAILMargo Workload Management APIf54748a1-72c1-4fb9-a64f-7e4b2b36ba54Retrieve the complete desired state for all workloads assigned to a device — Not Acceptable - Server cannot generate a response matching the Accept headerGET/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments406500expected HTTP 406, got 500
PASSMargo Workload Management APIe0358da8-3b31-4278-af5f-84d5e347bacdRetrieve an individual ApplicationDeployment YAML file — Deployment not found for the given digestGET/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
PASSMargo Workload Management APIaee967e3-204c-4193-b500-2559110e5c02Report deployment status — Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/status400400
FAILMargo Workload Management API387e5c5b-1a88-42a8-8c8d-e46e7aa20865Report deployment status — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/status401400expected HTTP 401, got 400
FAILMargo Workload Management API292d8e91-d376-4d2b-81d9-7c44cbc89ef3Report deployment status — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/status403400expected HTTP 403, got 400
FAILMargo Workload Management API6e674338-64ef-434c-9905-3ddff3d14877Report deployment status — Request body includes a semantic error.POST/api/v1/clients/client-f76a9a593484a08f-1786955850/deployments/deployment-none-00000000/status422400expected HTTP 422, got 400
+ + \ No newline at end of file diff --git a/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083738.html b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083738.html new file mode 100644 index 0000000..6054829 --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_083738.html @@ -0,0 +1,399 @@ + + + + + WFM Conformance Report — silver + + + +

Margo WFM Conformance Report

+
+ Group: silver  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T08:37:39.525Z +
+ +
+ ❌ 11 passed, 17 failed, 28 total +
+ +

Scenario Summary

+ + + + + + + + + + + +
ScenarioTotalPassedFailed
Margo Workload Management API281117
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSMargo Workload Management APIc42f4b7d-992a-4af0-924b-2eb4d787678aDownload Root CA certificate — Root CA certificateGET/api/v1/onboarding/certificate200200
PASSMargo Workload Management API0b95ee4e-dc64-4119-b07e-69c3342da26aComplete onboarding with client certificate — New client onboarded successfully.POST/api/v1/onboarding201201
PASSMargo Workload Management API0510e725-a124-415f-a9b9-0d369e1d94e2Report device capabilities — Capabilities reported successfullyPOST/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858201201
PASSMargo Workload Management API8bb41ecf-4010-4dd0-ba9e-11033cfe66cdUpdate device capabilities (Update) — Capabilities reported successfullyPUT/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858201201
PASSMargo Workload Management API195c5f23-c8c7-491a-b622-3ce29a0aa9c4Retrieve bundle information for a specific device and digest — Bundle archive (immutable)GET/api/v1/clients/client-27db0ab545d70711-1786955858/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API2bd8b6a4-ac94-435b-a365-42f07a064bc3Retrieve the complete desired state for all workloads assigned to a device — Manifest returned in the negotiated formatGET/api/v1/clients/client-27db0ab545d70711-1786955858/deployments200200
PASSMargo Workload Management API36fdd629-6c79-4991-86a2-49be8dbcf96fRetrieve an individual ApplicationDeployment YAML file — 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. +GET/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0Report deployment status — The deployment status was added, or updated, successfully.POST/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/status200400
FAILMargo Workload Management APIf9e10c20-8474-47ec-81c0-fc7c0823891dComplete onboarding with client certificate — Invalid certificate format or structure.POST/api/v1/onboarding400201expected HTTP 400, got 201
FAILMargo Workload Management APIe89bca4b-f257-434a-8397-d604c2b42eb8Complete onboarding with client certificate — Client certificate not trusted or client rejected.POST/api/v1/onboarding403201expected HTTP 403, got 201
FAILMargo Workload Management APIf206fb46-f592-45ea-a6f1-6569371ee515Report device capabilities — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.POST/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858400201expected HTTP 400, got 201
FAILMargo Workload Management API5fc47546-2c1a-4956-9b6a-cfdfb31b88f6Report device capabilities — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858401400expected HTTP 401, got 400
FAILMargo Workload Management API066c0155-a489-428e-9535-dabb36c7aaf6Report device capabilities — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858403400expected HTTP 403, got 400
FAILMargo Workload Management APIa3f7146c-5c7f-41f1-82d4-9ed75c84ec24Report device capabilities — Request body includes a semantic error.POST/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858422400expected HTTP 422, got 400
FAILMargo Workload Management APIeb9e178c-5df0-420c-8169-c223cc174a86Update device capabilities (Update) — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.PUT/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858400201expected HTTP 400, got 201
FAILMargo Workload Management API7b600483-4a8d-41ea-957c-88600e2a5f83Update device capabilities (Update) — Signature verification failed. Ensure you are signing with the correct X.509 private key.PUT/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858401400expected HTTP 401, got 400
FAILMargo Workload Management API6fb8f5bb-2932-4287-adb3-4e2f0b477a90Update device capabilities (Update) — Client certificate is not trusted or has been revoked.PUT/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858403400expected HTTP 403, got 400
FAILMargo Workload Management API8ec05b96-3f1d-4030-b2c6-67c9e98bf811Update device capabilities (Update) — Request body includes a semantic error.PUT/api/v1/clients/client-27db0ab545d70711-1786955858/capabilities/client-27db0ab545d70711-1786955858422400expected HTTP 422, got 400
FAILMargo Workload Management API5755e4a7-8329-4ceb-b210-8c41e6423569Retrieve bundle information for a specific device and digest — Representation not modifiedGET/api/v1/clients/client-27db0ab545d70711-1786955858/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000304404expected HTTP 304, got 404
FAILMargo Workload Management APIa7d2c754-66c3-4e45-aecb-987e481d9343Retrieve bundle information for a specific device and digest — Invalid request.GET/api/v1/clients/client-27db0ab545d70711-1786955858/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000400404expected HTTP 400, got 404
PASSMargo Workload Management API80315591-d033-4c57-8d63-9979889e6317Retrieve bundle information for a specific device and digest — Bundle not found for the given digestGET/api/v1/clients/client-27db0ab545d70711-1786955858/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
FAILMargo Workload Management API17a2b787-ca67-4dd6-a72b-27cd1290bebcRetrieve the complete desired state for all workloads assigned to a device — Not Modified - Manifest has not changedGET/api/v1/clients/client-27db0ab545d70711-1786955858/deployments304200expected HTTP 304, got 200
FAILMargo Workload Management APIf54748a1-72c1-4fb9-a64f-7e4b2b36ba54Retrieve the complete desired state for all workloads assigned to a device — Not Acceptable - Server cannot generate a response matching the Accept headerGET/api/v1/clients/client-27db0ab545d70711-1786955858/deployments406500expected HTTP 406, got 500
PASSMargo Workload Management APIe0358da8-3b31-4278-af5f-84d5e347bacdRetrieve an individual ApplicationDeployment YAML file — Deployment not found for the given digestGET/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
PASSMargo Workload Management APIaee967e3-204c-4193-b500-2559110e5c02Report deployment status — Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.POST/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/status400400
FAILMargo Workload Management API387e5c5b-1a88-42a8-8c8d-e46e7aa20865Report deployment status — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/status401400expected HTTP 401, got 400
FAILMargo Workload Management API292d8e91-d376-4d2b-81d9-7c44cbc89ef3Report deployment status — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/status403400expected HTTP 403, got 400
FAILMargo Workload Management API6e674338-64ef-434c-9905-3ddff3d14877Report deployment status — Request body includes a semantic error.POST/api/v1/clients/client-27db0ab545d70711-1786955858/deployments/deployment-none-00000000/status422400expected HTTP 422, got 400
+ + \ No newline at end of file diff --git a/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084449.html b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084449.html new file mode 100644 index 0000000..920fef5 --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084449.html @@ -0,0 +1,399 @@ + + + + + WFM Conformance Report — silver + + + +

Margo WFM Conformance Report

+
+ Group: silver  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T08:44:50.821Z +
+ +
+ ❌ 11 passed, 17 failed, 28 total +
+ +

Scenario Summary

+ + + + + + + + + + + +
ScenarioTotalPassedFailed
Margo Workload Management API281117
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSMargo Workload Management APIc42f4b7d-992a-4af0-924b-2eb4d787678aDownload Root CA certificate — Root CA certificateGET/api/v1/onboarding/certificate200200
PASSMargo Workload Management API0b95ee4e-dc64-4119-b07e-69c3342da26aComplete onboarding with client certificate — New client onboarded successfully.POST/api/v1/onboarding201201
PASSMargo Workload Management API0510e725-a124-415f-a9b9-0d369e1d94e2Report device capabilities — Capabilities reported successfullyPOST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289201201
PASSMargo Workload Management API8bb41ecf-4010-4dd0-ba9e-11033cfe66cdUpdate device capabilities (Update) — Capabilities reported successfullyPUT/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289201201
PASSMargo Workload Management API195c5f23-c8c7-491a-b622-3ce29a0aa9c4Retrieve bundle information for a specific device and digest — Bundle archive (immutable)GET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API2bd8b6a4-ac94-435b-a365-42f07a064bc3Retrieve the complete desired state for all workloads assigned to a device — Manifest returned in the negotiated formatGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments200200
PASSMargo Workload Management API36fdd629-6c79-4991-86a2-49be8dbcf96fRetrieve an individual ApplicationDeployment YAML file — 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. +GET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0Report deployment status — The deployment status was added, or updated, successfully.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/status200400
FAILMargo Workload Management APIf9e10c20-8474-47ec-81c0-fc7c0823891dComplete onboarding with client certificate — Invalid certificate format or structure.POST/api/v1/onboarding400201expected HTTP 400, got 201
FAILMargo Workload Management APIe89bca4b-f257-434a-8397-d604c2b42eb8Complete onboarding with client certificate — Client certificate not trusted or client rejected.POST/api/v1/onboarding403201expected HTTP 403, got 201
FAILMargo Workload Management APIf206fb46-f592-45ea-a6f1-6569371ee515Report device capabilities — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289400201expected HTTP 400, got 201
FAILMargo Workload Management API5fc47546-2c1a-4956-9b6a-cfdfb31b88f6Report device capabilities — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289401400expected HTTP 401, got 400
FAILMargo Workload Management API066c0155-a489-428e-9535-dabb36c7aaf6Report device capabilities — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289403400expected HTTP 403, got 400
FAILMargo Workload Management APIa3f7146c-5c7f-41f1-82d4-9ed75c84ec24Report device capabilities — Request body includes a semantic error.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289422400expected HTTP 422, got 400
FAILMargo Workload Management APIeb9e178c-5df0-420c-8169-c223cc174a86Update device capabilities (Update) — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.PUT/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289400201expected HTTP 400, got 201
FAILMargo Workload Management API7b600483-4a8d-41ea-957c-88600e2a5f83Update device capabilities (Update) — Signature verification failed. Ensure you are signing with the correct X.509 private key.PUT/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289401400expected HTTP 401, got 400
FAILMargo Workload Management API6fb8f5bb-2932-4287-adb3-4e2f0b477a90Update device capabilities (Update) — Client certificate is not trusted or has been revoked.PUT/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289403400expected HTTP 403, got 400
FAILMargo Workload Management API8ec05b96-3f1d-4030-b2c6-67c9e98bf811Update device capabilities (Update) — Request body includes a semantic error.PUT/api/v1/clients/client-59bb8f2f4877c07a-1786956289/capabilities/client-59bb8f2f4877c07a-1786956289422400expected HTTP 422, got 400
FAILMargo Workload Management API5755e4a7-8329-4ceb-b210-8c41e6423569Retrieve bundle information for a specific device and digest — Representation not modifiedGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000304404expected HTTP 304, got 404
FAILMargo Workload Management APIa7d2c754-66c3-4e45-aecb-987e481d9343Retrieve bundle information for a specific device and digest — Invalid request.GET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000400404expected HTTP 400, got 404
PASSMargo Workload Management API80315591-d033-4c57-8d63-9979889e6317Retrieve bundle information for a specific device and digest — Bundle not found for the given digestGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
FAILMargo Workload Management API17a2b787-ca67-4dd6-a72b-27cd1290bebcRetrieve the complete desired state for all workloads assigned to a device — Not Modified - Manifest has not changedGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments304200expected HTTP 304, got 200
FAILMargo Workload Management APIf54748a1-72c1-4fb9-a64f-7e4b2b36ba54Retrieve the complete desired state for all workloads assigned to a device — Not Acceptable - Server cannot generate a response matching the Accept headerGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments406500expected HTTP 406, got 500
PASSMargo Workload Management APIe0358da8-3b31-4278-af5f-84d5e347bacdRetrieve an individual ApplicationDeployment YAML file — Deployment not found for the given digestGET/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
PASSMargo Workload Management APIaee967e3-204c-4193-b500-2559110e5c02Report deployment status — Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/status400400
FAILMargo Workload Management API387e5c5b-1a88-42a8-8c8d-e46e7aa20865Report deployment status — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/status401400expected HTTP 401, got 400
FAILMargo Workload Management API292d8e91-d376-4d2b-81d9-7c44cbc89ef3Report deployment status — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/status403400expected HTTP 403, got 400
FAILMargo Workload Management API6e674338-64ef-434c-9905-3ddff3d14877Report deployment status — Request body includes a semantic error.POST/api/v1/clients/client-59bb8f2f4877c07a-1786956289/deployments/deployment-none-00000000/status422400expected HTTP 422, got 400
+ + \ No newline at end of file diff --git a/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084515.html b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084515.html new file mode 100644 index 0000000..cae2490 --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084515.html @@ -0,0 +1,399 @@ + + + + + WFM Conformance Report — silver + + + +

Margo WFM Conformance Report

+
+ Group: silver  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T08:45:16.655Z +
+ +
+ ❌ 11 passed, 17 failed, 28 total +
+ +

Scenario Summary

+ + + + + + + + + + + +
ScenarioTotalPassedFailed
Margo Workload Management API281117
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSMargo Workload Management APIc42f4b7d-992a-4af0-924b-2eb4d787678aDownload Root CA certificate — Root CA certificateGET/api/v1/onboarding/certificate200200
PASSMargo Workload Management API0b95ee4e-dc64-4119-b07e-69c3342da26aComplete onboarding with client certificate — New client onboarded successfully.POST/api/v1/onboarding201201
PASSMargo Workload Management API0510e725-a124-415f-a9b9-0d369e1d94e2Report device capabilities — Capabilities reported successfullyPOST/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315201201
PASSMargo Workload Management API8bb41ecf-4010-4dd0-ba9e-11033cfe66cdUpdate device capabilities (Update) — Capabilities reported successfullyPUT/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315201201
PASSMargo Workload Management API195c5f23-c8c7-491a-b622-3ce29a0aa9c4Retrieve bundle information for a specific device and digest — Bundle archive (immutable)GET/api/v1/clients/client-c27150e5a8ec4992-1786956315/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API2bd8b6a4-ac94-435b-a365-42f07a064bc3Retrieve the complete desired state for all workloads assigned to a device — Manifest returned in the negotiated formatGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments200200
PASSMargo Workload Management API36fdd629-6c79-4991-86a2-49be8dbcf96fRetrieve an individual ApplicationDeployment YAML file — 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. +GET/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0Report deployment status — The deployment status was added, or updated, successfully.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/status200400
FAILMargo Workload Management APIf9e10c20-8474-47ec-81c0-fc7c0823891dComplete onboarding with client certificate — Invalid certificate format or structure.POST/api/v1/onboarding400201expected HTTP 400, got 201
FAILMargo Workload Management APIe89bca4b-f257-434a-8397-d604c2b42eb8Complete onboarding with client certificate — Client certificate not trusted or client rejected.POST/api/v1/onboarding403201expected HTTP 403, got 201
FAILMargo Workload Management APIf206fb46-f592-45ea-a6f1-6569371ee515Report device capabilities — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315400201expected HTTP 400, got 201
FAILMargo Workload Management API5fc47546-2c1a-4956-9b6a-cfdfb31b88f6Report device capabilities — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315401400expected HTTP 401, got 400
FAILMargo Workload Management API066c0155-a489-428e-9535-dabb36c7aaf6Report device capabilities — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315403400expected HTTP 403, got 400
FAILMargo Workload Management APIa3f7146c-5c7f-41f1-82d4-9ed75c84ec24Report device capabilities — Request body includes a semantic error.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315422400expected HTTP 422, got 400
FAILMargo Workload Management APIeb9e178c-5df0-420c-8169-c223cc174a86Update device capabilities (Update) — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.PUT/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315400201expected HTTP 400, got 201
FAILMargo Workload Management API7b600483-4a8d-41ea-957c-88600e2a5f83Update device capabilities (Update) — Signature verification failed. Ensure you are signing with the correct X.509 private key.PUT/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315401400expected HTTP 401, got 400
FAILMargo Workload Management API6fb8f5bb-2932-4287-adb3-4e2f0b477a90Update device capabilities (Update) — Client certificate is not trusted or has been revoked.PUT/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315403400expected HTTP 403, got 400
FAILMargo Workload Management API8ec05b96-3f1d-4030-b2c6-67c9e98bf811Update device capabilities (Update) — Request body includes a semantic error.PUT/api/v1/clients/client-c27150e5a8ec4992-1786956315/capabilities/client-c27150e5a8ec4992-1786956315422400expected HTTP 422, got 400
FAILMargo Workload Management API5755e4a7-8329-4ceb-b210-8c41e6423569Retrieve bundle information for a specific device and digest — Representation not modifiedGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000304404expected HTTP 304, got 404
FAILMargo Workload Management APIa7d2c754-66c3-4e45-aecb-987e481d9343Retrieve bundle information for a specific device and digest — Invalid request.GET/api/v1/clients/client-c27150e5a8ec4992-1786956315/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000400404expected HTTP 400, got 404
PASSMargo Workload Management API80315591-d033-4c57-8d63-9979889e6317Retrieve bundle information for a specific device and digest — Bundle not found for the given digestGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
FAILMargo Workload Management API17a2b787-ca67-4dd6-a72b-27cd1290bebcRetrieve the complete desired state for all workloads assigned to a device — Not Modified - Manifest has not changedGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments304200expected HTTP 304, got 200
FAILMargo Workload Management APIf54748a1-72c1-4fb9-a64f-7e4b2b36ba54Retrieve the complete desired state for all workloads assigned to a device — Not Acceptable - Server cannot generate a response matching the Accept headerGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments406500expected HTTP 406, got 500
PASSMargo Workload Management APIe0358da8-3b31-4278-af5f-84d5e347bacdRetrieve an individual ApplicationDeployment YAML file — Deployment not found for the given digestGET/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
PASSMargo Workload Management APIaee967e3-204c-4193-b500-2559110e5c02Report deployment status — Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/status400400
FAILMargo Workload Management API387e5c5b-1a88-42a8-8c8d-e46e7aa20865Report deployment status — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/status401400expected HTTP 401, got 400
FAILMargo Workload Management API292d8e91-d376-4d2b-81d9-7c44cbc89ef3Report deployment status — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/status403400expected HTTP 403, got 400
FAILMargo Workload Management API6e674338-64ef-434c-9905-3ddff3d14877Report deployment status — Request body includes a semantic error.POST/api/v1/clients/client-c27150e5a8ec4992-1786956315/deployments/deployment-none-00000000/status422400expected HTTP 422, got 400
+ + \ No newline at end of file diff --git a/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084810.html b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084810.html new file mode 100644 index 0000000..549b835 --- /dev/null +++ b/Runner/wfm-supplier/wfm-scenario-report-silver-1_20260817_084810.html @@ -0,0 +1,399 @@ + + + + + WFM Conformance Report — silver + + + +

Margo WFM Conformance Report

+
+ Group: silver  |  + Claimed App Version: 1.0.0-rc.2  |  + CTT Margo Version: 1.0.0-rc.2  |  + WFM: https://symphony.machine:8082/v1alpha2/margo  |  + Run: 2026-08-17T08:48:11.881Z +
+ +
+ ❌ 11 passed, 17 failed, 28 total +
+ +

Scenario Summary

+ + + + + + + + + + + +
ScenarioTotalPassedFailed
Margo Workload Management API281117
+ +

Step Details

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusScenarioStepNameMethodEndpointExpectedActualFailure Reason
PASSMargo Workload Management APIc42f4b7d-992a-4af0-924b-2eb4d787678aDownload Root CA certificate — Root CA certificateGET/api/v1/onboarding/certificate200200
PASSMargo Workload Management API0b95ee4e-dc64-4119-b07e-69c3342da26aComplete onboarding with client certificate — New client onboarded successfully.POST/api/v1/onboarding201201
PASSMargo Workload Management API0510e725-a124-415f-a9b9-0d369e1d94e2Report device capabilities — Capabilities reported successfullyPOST/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490201201
PASSMargo Workload Management API8bb41ecf-4010-4dd0-ba9e-11033cfe66cdUpdate device capabilities (Update) — Capabilities reported successfullyPUT/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490201201
PASSMargo Workload Management API195c5f23-c8c7-491a-b622-3ce29a0aa9c4Retrieve bundle information for a specific device and digest — Bundle archive (immutable)GET/api/v1/clients/client-a111627844c95c37-1786956490/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API2bd8b6a4-ac94-435b-a365-42f07a064bc3Retrieve the complete desired state for all workloads assigned to a device — Manifest returned in the negotiated formatGET/api/v1/clients/client-a111627844c95c37-1786956490/deployments200200
PASSMargo Workload Management API36fdd629-6c79-4991-86a2-49be8dbcf96fRetrieve an individual ApplicationDeployment YAML file — 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. +GET/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000200404
PASSMargo Workload Management API6283ddb7-ae5b-4602-ae16-fa7b3aff0bc0Report deployment status — The deployment status was added, or updated, successfully.POST/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/status200400
FAILMargo Workload Management APIf9e10c20-8474-47ec-81c0-fc7c0823891dComplete onboarding with client certificate — Invalid certificate format or structure.POST/api/v1/onboarding400201expected HTTP 400, got 201
FAILMargo Workload Management APIe89bca4b-f257-434a-8397-d604c2b42eb8Complete onboarding with client certificate — Client certificate not trusted or client rejected.POST/api/v1/onboarding403201expected HTTP 403, got 201
FAILMargo Workload Management APIf206fb46-f592-45ea-a6f1-6569371ee515Report device capabilities — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.POST/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490400201expected HTTP 400, got 201
FAILMargo Workload Management API5fc47546-2c1a-4956-9b6a-cfdfb31b88f6Report device capabilities — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490401400expected HTTP 401, got 400
FAILMargo Workload Management API066c0155-a489-428e-9535-dabb36c7aaf6Report device capabilities — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490403400expected HTTP 403, got 400
FAILMargo Workload Management APIa3f7146c-5c7f-41f1-82d4-9ed75c84ec24Report device capabilities — Request body includes a semantic error.POST/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490422400expected HTTP 422, got 400
FAILMargo Workload Management APIeb9e178c-5df0-420c-8169-c223cc174a86Update device capabilities (Update) — Missing or invalid content-digest header. Ensure the SHA256 hash of the payload is included.PUT/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490400201expected HTTP 400, got 201
FAILMargo Workload Management API7b600483-4a8d-41ea-957c-88600e2a5f83Update device capabilities (Update) — Signature verification failed. Ensure you are signing with the correct X.509 private key.PUT/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490401400expected HTTP 401, got 400
FAILMargo Workload Management API6fb8f5bb-2932-4287-adb3-4e2f0b477a90Update device capabilities (Update) — Client certificate is not trusted or has been revoked.PUT/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490403400expected HTTP 403, got 400
FAILMargo Workload Management API8ec05b96-3f1d-4030-b2c6-67c9e98bf811Update device capabilities (Update) — Request body includes a semantic error.PUT/api/v1/clients/client-a111627844c95c37-1786956490/capabilities/client-a111627844c95c37-1786956490422400expected HTTP 422, got 400
FAILMargo Workload Management API5755e4a7-8329-4ceb-b210-8c41e6423569Retrieve bundle information for a specific device and digest — Representation not modifiedGET/api/v1/clients/client-a111627844c95c37-1786956490/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000304404expected HTTP 304, got 404
FAILMargo Workload Management APIa7d2c754-66c3-4e45-aecb-987e481d9343Retrieve bundle information for a specific device and digest — Invalid request.GET/api/v1/clients/client-a111627844c95c37-1786956490/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000400404expected HTTP 400, got 404
PASSMargo Workload Management API80315591-d033-4c57-8d63-9979889e6317Retrieve bundle information for a specific device and digest — Bundle not found for the given digestGET/api/v1/clients/client-a111627844c95c37-1786956490/bundles/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
FAILMargo Workload Management API17a2b787-ca67-4dd6-a72b-27cd1290bebcRetrieve the complete desired state for all workloads assigned to a device — Not Modified - Manifest has not changedGET/api/v1/clients/client-a111627844c95c37-1786956490/deployments304200expected HTTP 304, got 200
FAILMargo Workload Management APIf54748a1-72c1-4fb9-a64f-7e4b2b36ba54Retrieve the complete desired state for all workloads assigned to a device — Not Acceptable - Server cannot generate a response matching the Accept headerGET/api/v1/clients/client-a111627844c95c37-1786956490/deployments406500expected HTTP 406, got 500
PASSMargo Workload Management APIe0358da8-3b31-4278-af5f-84d5e347bacdRetrieve an individual ApplicationDeployment YAML file — Deployment not found for the given digestGET/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/sha256:0000000000000000000000000000000000000000000000000000000000000000404404
PASSMargo Workload Management APIaee967e3-204c-4193-b500-2559110e5c02Report deployment status — Missing or invalid content-digest header. Ensure the SHA256 hash of the base64-encoded payload is included.POST/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/status400400
FAILMargo Workload Management API387e5c5b-1a88-42a8-8c8d-e46e7aa20865Report deployment status — Signature verification failed. Ensure you are signing with the correct X.509 private key.POST/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/status401400expected HTTP 401, got 400
FAILMargo Workload Management API292d8e91-d376-4d2b-81d9-7c44cbc89ef3Report deployment status — Client certificate is not trusted or has been revoked.POST/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/status403400expected HTTP 403, got 400
FAILMargo Workload Management API6e674338-64ef-434c-9905-3ddff3d14877Report deployment status — Request body includes a semantic error.POST/api/v1/clients/client-a111627844c95c37-1786956490/deployments/deployment-none-00000000/status422400expected HTTP 422, got 400
+ + \ No newline at end of file diff --git a/client-demo-brief.md b/client-demo-brief.md new file mode 100644 index 0000000..32221b3 --- /dev/null +++ b/client-demo-brief.md @@ -0,0 +1,18 @@ +# Margo Conformance Test Suite — Summary + +Margo defines how a **device** and a **WFM** (Workload Fleet Manager, the cloud/control-plane side) talk to each other over HTTPS. This suite lets a vendor who built *either side* prove their implementation follows that spec — without needing the other side's real system. We provide a correct mock stand-in, run real HTTP calls against it, and hand back a pass/fail report. + +## Two CLIs + +- **`conformance.sh`** — Data Generation. Builds test cases (from an OpenAPI spec, a Postman collection, or scenario files) and organizes them into named groups. +- **`run-tests.sh`** — Execution / Runner. Picks a group, fires the actual HTTP calls at a real or mock system, and produces the HTML report. + +## Three personas + +- **Device Supplier** — vendor brings a real device; we provide a mock WFM to test it against. +- **WFM Supplier** — vendor brings a real WFM; we provide a mock device that fires test calls at it. +- **Application Supplier** — validates that an application package is correctly structured per spec. + +## Why it holds up + +Tests trace directly to the spec, cover both success and deliberately-broken cases (bad signature, bad cert, etc.), and every report row is a real request/response — expected vs. actual, side by side. diff --git a/conformance.sh b/conformance.sh new file mode 100755 index 0000000..f816f2b --- /dev/null +++ b/conformance.sh @@ -0,0 +1,1045 @@ +#!/bin/bash + +################################################################################ +# Conformance Test Case Generator CLI +# Purpose: Create and prepare test cases for Margo Personas +# Usage: ./conformance.sh +################################################################################ + +set -euo pipefail + +# Get script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFORMANCE_DIR="$SCRIPT_DIR" +DATA_GEN_DIR="$CONFORMANCE_DIR/Data-Generator" + +################################################################################ +# Logging Functions +################################################################################ + +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] 📝 $*" +} + +success() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ✅ $*" +} + +error() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ❌ $*" >&2 + exit 1 +} + +info() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ℹ️ $*" +} + +warn() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ⚠️ $*" +} + +################################################################################ +# WFM Supplier Test Case Generation - with OpenAPI Spec Path +################################################################################ + +generate_wfm_tests() { + local openapi_spec_path="${1:-}" + + if [[ -z "$openapi_spec_path" ]]; then + info "Provide the OpenAPI Specification path" + info "Can be: URL (https://...) or local file path" + info "Example: https://raw.githubusercontent.com/margo/specification/.../openapi.yaml" + info "Or: /path/to/local/openapi.yaml" + read -p "OpenAPI Spec Path: " openapi_spec_path + fi + + if [[ -z "$openapi_spec_path" ]]; then + error "OpenAPI Spec path cannot be empty" + fi + + log "🚀 Generating WFM Supplier test cases..." + log "OpenAPI Spec: $openapi_spec_path" + + # Create output directory + mkdir -p "$DATA_GEN_DIR/wfm-supplier" + + # Use Portman to generate Postman collection from OpenAPI + cd "$CONFORMANCE_DIR/wfm-supplier" + + # The npm package is "portman" is unrelated (a "Socket port manager"); the + # real OpenAPI-to-Postman tool is "@apideck/portman". Pinned to 1.34.1 + # because 1.35.0 pulled in @faker-js/faker@10, which is ESM-only and + # crashes under Node <20 (this environment runs Node 18). + local portman_cmd=(portman) + if ! command -v portman &> /dev/null; then + info "Portman not installed globally; running via npx (no install/permissions needed)..." + portman_cmd=(npx --yes @apideck/portman@1.34.1) + fi + + log "🔧 Running Portman to generate test cases..." + + # Determine if spec is a URL or local file + local spec_file="" + + if [[ "$openapi_spec_path" == https://* || "$openapi_spec_path" == http://* ]]; then + # Download from URL + log "📥 Downloading OpenAPI specification from URL..." + spec_file="/tmp/openapi_spec_$$.yaml" + if ! curl -sSL "$openapi_spec_path" -o "$spec_file" 2>/dev/null; then + error "Could not download OpenAPI spec from URL: $openapi_spec_path" + fi + log "✅ Downloaded OpenAPI spec" + else + # Local file path + if [[ ! -f "$openapi_spec_path" ]]; then + error "OpenAPI Spec file not found: $openapi_spec_path" + fi + spec_file="$openapi_spec_path" + log "✅ Using local OpenAPI spec: $spec_file" + fi + + # Validate spec file + if [[ ! -f "$spec_file" ]]; then + error "OpenAPI Spec file does not exist: $spec_file" + fi + + # Validate spec file is not empty + if [[ ! -s "$spec_file" ]]; then + error "OpenAPI Spec file is empty: $spec_file" + fi + + # Run Portman + log "📋 Generating Postman collection..." + if ! "${portman_cmd[@]}" -l "$spec_file" -o postman_collection.json 2>/dev/null; then + error "Portman generation failed" + fi + + log "✅ Test cases generated successfully" + log "📋 Copying postman_collection.json to Data-Generator..." + + # Copy to Data-Generator + cp postman_collection.json "$DATA_GEN_DIR/wfm-supplier/" + + # Copy newman data if exists + if [[ -d "newman-data" ]]; then + log "📦 Copying newman data files..." + cp -r newman-data "$DATA_GEN_DIR/wfm-supplier/" 2>/dev/null || true + fi + + # Clean up temp file if it was downloaded + if [[ "$openapi_spec_path" == https://* || "$openapi_spec_path" == http://* ]]; then + rm -f "$spec_file" + fi + + success "WFM test cases generated and prepared" + success "Output: $DATA_GEN_DIR/wfm-supplier/" + + # Show summary + info "Generated files:" + ls -lh "$DATA_GEN_DIR/wfm-supplier/" | tail -n +2 | awk '{print " - " $9 " (" $5 ")"}' +} + +################################################################################ +# WFM Supplier Functional Tests - Manual Test Cases (MARGO Template) +################################################################################ + +generate_wfm_functional_tests() { + local postman_collection_path="${1:-}" + + if [[ -z "$postman_collection_path" ]]; then + info "Provide the path to Postman collection JSON file" + info "Path to manual/hand-crafted Postman collection" + info "Example: /path/to/postman_collection.json" + info "Or place files in: $CONFORMANCE_DIR/manual-test-cases/" + read -p "Postman Collection JSON Path: " postman_collection_path + fi + + if [[ -z "$postman_collection_path" ]]; then + error "Postman collection path cannot be empty" + fi + + # Expand tilde if used + postman_collection_path="${postman_collection_path/\~/$HOME}" + + log "🚀 Setting up WFM Supplier Functional Tests (MARGO Template)..." + log "Collection: $postman_collection_path" + + # Create output directory + mkdir -p "$DATA_GEN_DIR/wfm-supplier" + + # Validate file exists + if [[ ! -f "$postman_collection_path" ]]; then + error "Postman collection file not found: $postman_collection_path" + fi + + # Validate file is not empty + if [[ ! -s "$postman_collection_path" ]]; then + error "Postman collection file is empty: $postman_collection_path" + fi + + # Validate JSON format + log "📋 Validating JSON format..." + if ! jq empty "$postman_collection_path" 2>/dev/null; then + error "Invalid JSON format in: $postman_collection_path" + fi + + # Validate Postman collection structure (basic validation) + log "🔍 Validating Postman collection format..." + local has_info + has_info=$(jq '.info' "$postman_collection_path" 2>/dev/null) + + if [[ -z "$has_info" ]] || [[ "$has_info" == "null" ]]; then + error "Invalid Postman collection: missing 'info' field" + fi + + local has_items + has_items=$(jq '.item' "$postman_collection_path" 2>/dev/null) + + if [[ -z "$has_items" ]] || [[ "$has_items" == "null" ]]; then + error "Invalid Postman collection: missing 'item' field" + fi + + log "✅ Collection validation passed" + + # Get collection info + local collection_name + local item_count + collection_name=$(jq -r '.info.name' "$postman_collection_path") + item_count=$(jq '.item | length' "$postman_collection_path") + + log "📊 Collection Details:" + log " Name: $collection_name" + log " Test items: $item_count" + + # Copy collection to Data-Generator + log "📋 Copying Postman collection to Data-Generator..." + + cp "$postman_collection_path" "$DATA_GEN_DIR/wfm-supplier/postman_collection_functional.json" + + # Also create a marker file indicating this is functional tests + touch "$DATA_GEN_DIR/wfm-supplier/.functional-tests" + + success "WFM Functional Tests prepared successfully" + success "Output: $DATA_GEN_DIR/wfm-supplier/postman_collection_functional.json" + + info "Ready for test execution with Newman" +} + +################################################################################ +# Device Test Type Selection Menu +################################################################################ + +show_test_type_menu() { + echo "" + echo "What type of test-cases do you want to add?" + echo "1. OpenAPI spec based contract tests" + echo "2. Functional tests (Group-based test management)" + echo "" + echo "B) Back" + echo "Q) Quit" + echo "" +} + +################################################################################ +# Device Supplier Test Case Validation +################################################################################ + +validate_device_test_scenarios() { + local scenarios_path="${1:-}" + local assertions_path="${2:-}" + + # Validate test scenarios file + if [[ ! -f "$scenarios_path" ]]; then + error "Test scenarios file not found: $scenarios_path" + fi + + if [[ ! -s "$scenarios_path" ]]; then + error "Test scenarios file is empty: $scenarios_path" + fi + + # Validate JSON format + log "📋 Validating JSON format for test scenarios..." + if ! jq empty "$scenarios_path" 2>/dev/null; then + error "Invalid JSON format in test scenarios: $scenarios_path" + fi + + # Validate test scenarios structure + log "🔍 Validating test scenarios structure..." + local scenario_count + scenario_count=$(jq 'length' "$scenarios_path" 2>/dev/null) + + if [[ -z "$scenario_count" ]] || [[ "$scenario_count" == "0" ]]; then + error "Test scenarios file must contain at least one scenario" + fi + + # Check for required fields in each scenario + local has_required_fields + has_required_fields=$(jq '[.[] | has("id") and has("name") and has("steps")] | all' "$scenarios_path" 2>/dev/null) + + if [[ "$has_required_fields" != "true" ]]; then + error "Invalid test scenarios: each scenario must have 'id', 'name', and 'steps' fields" + fi + + # Check if assertions file exists + if [[ -f "$assertions_path" ]]; then + log "📋 Validating JSON format for assertions..." + if ! jq empty "$assertions_path" 2>/dev/null; then + error "Invalid JSON format in assertions file: $assertions_path" + fi + + log "🔍 Validating assertions structure..." + local has_endpoints + has_endpoints=$(jq 'has("endpoints")' "$assertions_path" 2>/dev/null) + + if [[ "$has_endpoints" != "true" ]]; then + warn "Assertions file does not have 'endpoints' section (non-critical)" + fi + else + warn "Assertions file not found at: $assertions_path (optional)" + fi + + log "✅ Validations passed" + + # Show scenarios summary + info "Test Scenarios Summary:" + jq -r '.[] | " - \(.id): \(.name)"' "$scenarios_path" | head -10 + + local total=$(jq 'length' "$scenarios_path") + if [[ $total -gt 10 ]]; then + info " ... and $((total - 10)) more scenarios" + fi +} + +################################################################################ +# Device Supplier Test Case Setup +################################################################################ + +generate_device_tests() { + local test_scenarios_path="${1:-}" + + if [[ -z "$test_scenarios_path" ]]; then + info "Provide the path to Device test scenarios JSON file" + info "Expected location: device-supplier/device-scenarios/test-scenarios.json" + info "Or use: $CONFORMANCE_DIR/device-supplier/device-scenarios/test-scenarios.json" + read -p "Test Scenarios JSON Path: " test_scenarios_path + fi + + if [[ -z "$test_scenarios_path" ]]; then + error "Test scenarios path cannot be empty" + fi + + # Expand tilde if used + test_scenarios_path="${test_scenarios_path/\~/$HOME}" + + # Check for assertions file + local assertions_path="$CONFORMANCE_DIR/device-supplier/manifests/assertions.json" + + # If test scenarios path is provided, try to find assertions nearby + if [[ "$test_scenarios_path" == *"device-scenarios"* ]]; then + assertions_path="${test_scenarios_path%/*}/../manifests/assertions.json" + fi + + log "🚀 Setting up Device Supplier Test Cases..." + log "Test scenarios: $test_scenarios_path" + log "Assertions file: $assertions_path" + + # Create output directory + mkdir -p "$DATA_GEN_DIR/device-supplier" + + # Validate test scenarios and assertions + validate_device_test_scenarios "$test_scenarios_path" "$assertions_path" + + # Copy test scenarios to Data-Generator + log "📋 Copying test scenarios to Data-Generator..." + cp "$test_scenarios_path" "$DATA_GEN_DIR/device-supplier/test-scenarios.json" + + # Copy assertions file if it exists + if [[ -f "$assertions_path" ]]; then + log "📋 Copying assertions file..." + cp "$assertions_path" "$DATA_GEN_DIR/device-supplier/assertions.json" + fi + + # Copy supporting files from device-supplier if they exist + if [[ -d "$CONFORMANCE_DIR/device-supplier/manifests" ]]; then + log "📦 Copying supporting manifest files..." + cp -r "$CONFORMANCE_DIR/device-supplier/manifests"/* "$DATA_GEN_DIR/device-supplier/" 2>/dev/null || true + fi + + # Create marker file + touch "$DATA_GEN_DIR/device-supplier/.device-scenarios" + + success "Device Supplier Test Cases prepared successfully" + success "Output: $DATA_GEN_DIR/device-supplier/" + + info "Generated files:" + ls -lh "$DATA_GEN_DIR/device-supplier/" | grep -E "\.(json|yaml)$" | awk '{print " - " $9 " (" $5 ")"}' +} + +################################################################################ +# Device Supplier Test Case Generation - OpenAPI Contract Tests +################################################################################ + +generate_device_openapi_tests() { + log "🚀 Generating Device Supplier - OpenAPI Contract Tests..." + + local api_url="${1:-}" + + if [[ -z "$api_url" ]]; then + info "Enter the Margo API URL for Device Supplier" + info "Example: https://symphony.machine:8082/v1alpha2/margo" + read -p "API URL: " api_url + fi + + if [[ -z "$api_url" ]]; then + error "API URL cannot be empty" + fi + + log "📥 Downloading OpenAPI specification..." + + # Create output directory + mkdir -p "$DATA_GEN_DIR/device-supplier" + + # Use Portman to generate Postman collection from OpenAPI + cd "$CONFORMANCE_DIR/device-supplier" 2>/dev/null || \ + error "device-supplier directory not found" + + # The npm package is "portman" is unrelated (a "Socket port manager"); the + # real OpenAPI-to-Postman tool is "@apideck/portman". Pinned to 1.34.1 + # because 1.35.0 pulled in @faker-js/faker@10, which is ESM-only and + # crashes under Node <20 (this environment runs Node 18). + local portman_cmd=(portman) + if ! command -v portman &> /dev/null; then + info "Portman not installed globally; running via npx (no install/permissions needed)..." + portman_cmd=(npx --yes @apideck/portman@1.34.1) + fi + + log "🔧 Running Portman to generate OpenAPI contract tests..." + + # Create a temporary OpenAPI spec file + local spec_file="/tmp/device_openapi_spec_$$.yaml" + if curl -sSL "$api_url/openapi" -o "$spec_file" 2>/dev/null; then + log "✅ Downloaded OpenAPI spec" + else + error "Could not download OpenAPI spec from $api_url" + fi + + # Generate Postman collection for device endpoints + "${portman_cmd[@]}" --spec "$spec_file" --output device_postman_collection.json 2>/dev/null || \ + error "Portman generation failed" + + log "✅ Contract tests generated" + log "📋 Copying device_postman_collection.json to Data-Generator..." + + # Copy to Data-Generator + cp device_postman_collection.json "$DATA_GEN_DIR/device-supplier/" + + # Copy newman data if exists + if [[ -d "newman-data" ]]; then + log "📦 Copying newman data files..." + cp -r newman-data "$DATA_GEN_DIR/device-supplier/" 2>/dev/null || true + fi + + # Clean up temp file + rm -f "$spec_file" + + success "Device OpenAPI contract tests generated" + success "Output: $DATA_GEN_DIR/device-supplier/" + success "Test file: device_postman_collection.json" + + # Show summary + info "Generated files:" + ls -lh "$DATA_GEN_DIR/device-supplier/" | tail -n +2 | awk '{print " - " $9 " (" $5 ")"}' +} + +################################################################################ +# Device Supplier Test Case Generation - MARGO Template Functional Tests +################################################################################ + +generate_device_margo_template_tests() { + log "🚀 Generating Device Supplier - MARGO Template Functional Tests..." + + # Create output directory + mkdir -p "$DATA_GEN_DIR/device-supplier" + + log "📥 Preparing test scenarios from MARGO template..." + + # Copy test scenarios from device-supplier + local source_file="$CONFORMANCE_DIR/device-supplier/device-scenarios/test-scenarios.json" + + if [[ ! -f "$source_file" ]]; then + error "Test scenarios not found at $source_file" + fi + + log "📋 Copying test-scenarios.json (MARGO template)..." + cp "$source_file" "$DATA_GEN_DIR/device-supplier/" + + # Copy additional test data files if they exist + if [[ -d "$CONFORMANCE_DIR/device-supplier/device-scenarios" ]]; then + log "📦 Copying additional test data files..." + cp -r "$CONFORMANCE_DIR/device-supplier/device-scenarios"/* \ + "$DATA_GEN_DIR/device-supplier/" 2>/dev/null || true + fi + + success "Device MARGO template functional tests generated" + success "Output: $DATA_GEN_DIR/device-supplier/" + success "Test file: test-scenarios.json" + + # Show summary + info "Generated files:" + ls -lh "$DATA_GEN_DIR/device-supplier/" | tail -n +2 | awk '{print " - " $9 " (" $5 ")"}' + + # Count scenarios + if [[ -f "$DATA_GEN_DIR/device-supplier/test-scenarios.json" ]]; then + local test_count=$(jq '.[] | .id' "$DATA_GEN_DIR/device-supplier/test-scenarios.json" 2>/dev/null | wc -l) + info "Total test scenarios: $test_count" + fi + + info "Test Type: MARGO Template with RFC 9421 Signature Validation" +} + +################################################################################ +# Persona Selection Menu +################################################################################ + +show_persona_menu() { + echo "" + echo "Which Margo Persona do you want to manage?" + echo "1. WFM Supplier " + echo "2. Device Supplier" + echo "" + echo "H) Help" + echo "Q) Quit" + echo "" +} + +show_help() { + cat << 'EOF' + +╔═══════════════════════════════════════════════════════════════════════════╗ +║ Conformance Test Case Generator - Help ║ +╚═══════════════════════════════════════════════════════════════════════════╝ + +DESCRIPTION: + This CLI generates test cases for Margo conformance testing. + It prepares test data for both WFM Supplier and Device Supplier personas. + + When you select WFM Supplier, you can prepare either OpenAPI-based tests or a functional Postman collection. + + When you select Device Supplier, you manage group-based device scenarios. + +USAGE: + ./conformance.sh # Interactive menu + ./conformance.sh wfm openapi [SPEC_PATH] # Generate WFM OpenAPI tests + ./conformance.sh wfm functional [PATH] # Prepare WFM Postman collection + ./conformance.sh device # Create/select Device groups + ./conformance.sh device [SCENARIOS] # Prepare Device scenarios + +PERSONA OPTIONS: + + WFM Supplier: + • Generates Postman collection from OpenAPI spec + • Tests API contracts via Newman + • Option 1: OpenAPI spec based (asks for spec path: URL or local file) + • Option 2: MARGO template (not yet implemented) + + Device Supplier: + • Interactive mode opens group management + • Command mode can prepare a scenario file or template data + • Template file: device-supplier/device-scenarios/TEMPLATE_custom_test_scenario.json + • See device-supplier/Final-Summary.md for complete schema documentation + +INTERACTIVE MENU: + 1 - Select WFM Supplier + 2 - Select Device Supplier group management + H/help - Show this help message + Q/quit - Exit the program + +EXAMPLES: + + 1. Interactive mode (menu-driven): + ./conformance.sh + + 2. Generate WFM tests with OpenAPI spec URL: + ./conformance.sh wfm https://raw.githubusercontent.com/margo/specification/.../openapi.yaml + + 3. Generate WFM tests with local OpenAPI spec file: + ./conformance.sh wfm /path/to/local/openapi.yaml + + 4. Generate Device tests with existing test-scenarios.json: + ./conformance.sh device "/home/margo/nitin/sandbox/conformance/device-supplier/device-scenarios/test-scenarios.json" + + 5. Generate Device tests with custom test scenarios: + ./conformance.sh device "/path/to/your/custom_test_scenarios.json" + + 6. View custom test scenario template: + cat device-supplier/device-scenarios/TEMPLATE_custom_test_scenario.json + +WHAT GETS GENERATED: + + WFM Supplier: + • postman_collection.json (92KB) - 8 API test cases + • newman-data/ - Test environment and certificates + • Location: Data-Generator/wfm-supplier/ + + Device Supplier (Option 1 - Existing): + • test-scenarios.json (34KB) - 7 pre-built conformance test scenarios + • assertions.json - Validation rules and assertions + • deployment-template.yaml - Supporting manifest files + • Location: Data-Generator/device-supplier/ + + Device Supplier (Option 2 - Custom): + • test-scenarios.json - Your custom test scenarios file + • assertions.json - Your custom assertions (if provided) + • Location: Data-Generator/device-supplier/ + • Template: device-supplier/device-scenarios/TEMPLATE_custom_test_scenario.json + +NEXT STEPS: + + After generating tests, use the execution CLI to run them: + ./run-tests.sh + ./run-tests.sh wfm + ./run-tests.sh device + +REQUIREMENTS: + + WFM: + • npm (for Portman) + • curl (to download OpenAPI spec from URL) + • OpenAPI specification file (URL or local path) + + Device: + • npm (for Portman) - if using OpenAPI contract tests + • jq (to parse test scenarios) - if using MARGO template + • Margo API endpoint or device-supplier/device-scenarios/test-scenarios.json + +EOF +} + +################################################################################ +# Group Management Functions +################################################################################ + +set_supplier_context() { + SUPPLIER="$1" + GROUP_DIR="$DATA_GEN_DIR/$SUPPLIER/groups" +} + +create_test_group() { + mkdir -p "$GROUP_DIR" + + # Group name + if [[ -z "${GROUP_NAME:-}" ]]; then + echo "" + read -p "Enter group name: " GROUP_NAME + [[ -z "$GROUP_NAME" ]] && error "Group name cannot be empty" + fi + + GROUP_PATH="$GROUP_DIR/$GROUP_NAME" + + # App Version + echo "" + read -p "Enter version of Margo Specification: " VERSION + [[ -z "$VERSION" ]] && VERSION="1.0.0-rc.2" + + # Description + echo "" + read -p "Enter a short description for group: " DESCRIPTION + [[ -z "$DESCRIPTION" ]] && DESCRIPTION="User created group" + + # Append mode + APPEND_MODE=false + if [[ -d "$GROUP_PATH" ]]; then + info "Using existing group: $GROUP_NAME" + APPEND_MODE=true + else + mkdir -p "$GROUP_PATH" + fi + + # Input folder + echo "" + read -p "Enter folder path containing JSON files: " INPUT_PATH + [[ ! -d "$INPUT_PATH" ]] && error "Provided path is not a folder!" + INPUT_PATH="$(realpath --relative-to="$CONFORMANCE_DIR" "$INPUT_PATH")" + + log " Reading all JSON files from folder..." + + ALL_TESTS=() + + shopt -s nullglob + files=("$INPUT_PATH"/*.json) + + if [[ ${#files[@]} -eq 0 ]]; then + error "No JSON files found in folder!" + fi + + for file in "${files[@]}"; do + filename=$(basename "$file") + log " Processing: $filename" + + # Walk only the real test-structure containers — Postman's "item" + # (folders/requests) and our device-scenario "steps" — and take + # each one's own .id. A plain ".. | .id?" also descends into + # request/response bodies, headers, and auth blocks, which can + # contain unrelated "id" fields (e.g. a fake deviceId in a test + # payload, or a UUID buried in a header) that aren't test-case IDs. + IDS=$(jq -r ' + def walk_ids: + if type == "object" then + (if has("id") then (.id | tostring) else empty end), + (if (.item? // empty) | type == "array" then .item[] | walk_ids else empty end), + (if (.steps? // empty) | type == "array" then .steps[] | walk_ids else empty end) + elif type == "array" then + .[] | walk_ids + else empty end; + walk_ids + ' "$file" 2>/dev/null || true) + + if [[ -z "$IDS" ]]; then + IDS=$(jq -r '.. | .name? // empty' "$file" 2>/dev/null \ + | sed 's/ /_/g' \ + | tr '[:upper:]' '[:lower:]') + fi + + while IFS= read -r id; do + [[ -n "$id" ]] && ALL_TESTS+=("$id") + done <<< "$IDS" + done + + if [[ ${#ALL_TESTS[@]} -eq 0 ]]; then + error "No test cases found in files" + fi + + log " Total extracted test cases: ${#ALL_TESTS[@]}" + + TESTS_JSON=$(printf '%s\n' "${ALL_TESTS[@]}" | jq -R . | jq -s 'unique') + + PERSONA="$SUPPLIER" + + if [[ "$APPEND_MODE" == true && -f "$GROUP_PATH/group.json" ]]; then + OLD_TESTS=$(jq '.testCases // []' "$GROUP_PATH/group.json") + OLD_PATHS=$(jq '.FolderPath // []' "$GROUP_PATH/group.json") + # Preserve flexibleOrder from the existing group.json — groups that opt + # into it (e.g. flex-order) rely on an empty testCases (= "run every + # scenario") plus this flag to run the fixed_first scenario first, then + # the rest in random order. Regenerating must not silently turn that off. + OLD_FLEXIBLE=$(jq -r '.flexibleOrder // false' "$GROUP_PATH/group.json" 2>/dev/null || echo false) + + jq -n \ + --arg name "$GROUP_NAME" \ + --arg version "$VERSION" \ + --arg persona "$PERSONA" \ + --arg desc "$DESCRIPTION" \ + --arg folder "$INPUT_PATH" \ + --argjson old "$OLD_TESTS" \ + --argjson new "$TESTS_JSON" \ + --argjson oldPaths "$OLD_PATHS" \ + --argjson flexibleOrder "$OLD_FLEXIBLE" \ + '{ + name: $name, + version: $version, + persona: $persona, + description: $desc, + FolderPath: ($oldPaths + [$folder] | unique), + flexibleOrder: $flexibleOrder, + testCases: (if $flexibleOrder then [] else ($old + $new | unique) end) + }' > "$GROUP_PATH/group.json" + + success " Reading JSON files, extracting test case IDs, and adding them to the group.json" + + else + jq -n \ + --arg name "$GROUP_NAME" \ + --arg version "$VERSION" \ + --arg persona "$PERSONA" \ + --arg desc "$DESCRIPTION" \ + --arg folder "$INPUT_PATH" \ + --argjson tests "$TESTS_JSON" \ + '{ + name: $name, + version: $version, + persona: $persona, + description: $desc, + FolderPath: [$folder], + testCases: $tests + }' > "$GROUP_PATH/group.json" + + success " Created new group.json" + fi + + info "Target Group Folder: $GROUP_PATH" +} + +group_management_menu() { + # safety check + if [[ -z "${GROUP_DIR:-}" ]]; then + error "GROUP_DIR not set. Please select supplier first." + fi + + while true; do + echo "" + echo "Enter a number to select an existing group or press 0 to create a new group" + echo "" + + echo "Available Groups" + echo "--------------------------------------" + + mkdir -p "$GROUP_DIR" + + mapfile -t groups < <( + find "$GROUP_DIR" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; + ) + + if [ ${#groups[@]} -eq 0 ]; then + echo " No groups available" + else + for i in "${!groups[@]}"; do + echo " $((i+1))) ${groups[i]}" + done + fi + + echo "" + echo "B → Back" + echo "Q → Quit" + echo "" + + read -p "Enter your choice: " choice + + # BACK + [[ "${choice,,}" == "b" ]] && return + + # QUIT + [[ "${choice,,}" == "q" ]] && { info "Exiting..."; exit 0; } + + # CREATE + if [[ "$choice" == "0" ]]; then + unset GROUP_NAME + create_test_group + + # EXISTING + elif [[ "$choice" =~ ^[0-9]+$ ]]; then + index=$((choice-1)) + + if [[ -n "${groups[index]}" ]]; then + GROUP_NAME="${groups[index]}" + info "Selected existing group: $GROUP_NAME" + create_test_group + else + warn "Invalid group number" + continue + fi + + else + warn "Invalid choice" + continue + fi + + echo "" + echo "Options:" + echo " B → Back" + echo " Q → Quit" + echo "" + + read -p "Select option: " post_choice + + case "${post_choice,,}" in + b) continue ;; + q) info "Exiting..."; exit 0 ;; + *) warn "Invalid option" ;; + esac + done +} + +list_test_groups() { + mkdir -p "$GROUP_DIR" + + if ls -d "$GROUP_DIR"/*/ > /dev/null 2>&1; then + for dir in "$GROUP_DIR"/*/; do + echo " - $(basename "$dir")" + done + else + echo "No groups found" + fi +} + +################################################################################ +# Interactive Menu Loop +################################################################################ + +interactive_mode() { + while true; do + show_persona_menu + + read -p "Select option (1-2, H, or Q): " choice + + case "${choice,,}" in + 1|wfm) + echo "" + info "You selected: WFM Supplier" + + while true; do + show_test_type_menu + read -p "Select test type (1-2, B, or Q): " test_choice + + case "${test_choice,,}" in + + 1|openapi|contract) + echo "" + read -p "Enter OpenAPI Spec Path: " spec_path + generate_wfm_tests "$spec_path" + ;; + + 2|margo|functional|template) + echo "" + info "Functional Test Mode Selected" + + set_supplier_context "wfm-supplier" + group_management_menu + ;; + + b|back) + break + ;; + + q|quit) + info "Exiting..." + exit 0 + ;; + + *) + warn "Invalid option" + ;; + esac + done + ;; + 2|device) + echo "" + info "You selected: Device Supplier" + echo "" + + TEMPLATE_PATH="$CONFORMANCE_DIR/device-supplier/device-scenarios/../docs/template.md" + TEMPLATE_PATH="$(realpath "$TEMPLATE_PATH" 2>/dev/null || echo "$TEMPLATE_PATH")" + + echo "!! WARNING !!" + echo "================================================" + echo "Please ensure that all test cases are developed using the Margo template." + echo "" + echo "Template reference: $TEMPLATE_PATH" + + # Go directly to group-based selection + set_supplier_context "device-supplier" + group_management_menu + ;; + + h|help) + show_help + ;; + q|quit) + info "Exiting..." + exit 0 + ;; + *) + error "Invalid option. Please select 1, 2, H, or Q" + ;; + esac + + echo "" + read -p "Press Enter to continue or Q to quit: " continue_choice + if [[ "${continue_choice,,}" == "q" ]]; then + info "Exiting..." + exit 0 + fi + clear + done +} + +################################################################################ +# Command Line Argument Parsing +################################################################################ + +main() { + # Show welcome message + cat << 'EOF' +╔═══════════════════════════════════════════════════════════════════════════╗ +║ Margo Conformance Test Case Generator ║ +║ Create test cases for API and conformance testing ║ +╚═══════════════════════════════════════════════════════════════════════════╝ + +EOF + + # No arguments - show interactive menu + if [[ $# -eq 0 ]]; then + interactive_mode + exit 0 + fi + + # Parse command line arguments + local command="${1,,}" + + case "$command" in + wfm) + local wfm_type="${2,,}" + case "$wfm_type" in + openapi|contract) + generate_wfm_tests "${3:-}" + ;; + margo|functional|template) + generate_wfm_functional_tests "${3:-}" + ;; + "") + # No subcommand - use as spec path for backward compatibility + generate_wfm_tests "${2:-}" + ;; + *) + error "Unknown WFM test type: $wfm_type +Usage: ./conformance.sh wfm [openapi|functional] [path]" + ;; + esac + ;; + device) + local device_arg="${2:-}" + + # If second argument is a file path, use it directly + if [[ -f "$device_arg" ]]; then + generate_device_tests "$device_arg" + exit 0 + fi + + local device_type="${device_arg,,}" + case "$device_type" in + openapi|contract) + generate_device_openapi_tests "${3:-}" + ;; + margo|functional|template|scenarios) + generate_device_margo_template_tests + ;; + "") + # No device type specified - use generate_device_tests for interactive path prompt + generate_device_tests "" + ;; + *) + # Try to expand and check if it's a file path + local expanded_path="${device_arg/\~/$HOME}" + if [[ -f "$expanded_path" ]]; then + generate_device_tests "$expanded_path" + else + error "Unknown device option: $device_type +Usage: ./conformance.sh device [/path/to/scenarios.json|openapi|margo]" + fi + ;; + esac + ;; + help|-h|--help) + show_help + ;; + *) + error "Unknown command: $command + +Usage: ./conformance.sh [wfm|device|help] + +Run './conformance.sh help' for detailed instructions." + ;; + esac +} + +# Run main function +main "$@" diff --git a/conformance_cli.sh b/conformance_cli.sh new file mode 100755 index 0000000..e92be31 --- /dev/null +++ b/conformance_cli.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WFM_DIR="$ROOT_DIR/wfm-supplier" +DEVICE_DIR="$ROOT_DIR/device-supplier" + +# ============================================ +# Utility Functions (Like wfm.sh pattern) +# ============================================ +run_cmd() { + local dir="$1" + local msg="$2" + shift 2 + echo "$msg" + (cd "$dir" && "$@") + local rc=$? + if [[ $rc -eq 0 ]]; then + echo "Status: SUCCESS" + else + echo "Status: FAILED (exit code: $rc)" + fi + # Only prompt for input if running interactively + if [[ -t 0 ]]; then + read -p "Press Enter to continue..." _ + fi + return 0 +} + +show_menu() { + local title="$1" + shift + local options=("$@") + + while true; do + clear + echo "==============================" + echo " $title" + echo "==============================" + echo + for i in "${!options[@]}"; do + echo " $((i+1)). ${options[$i]}" + done + echo + read -p "Enter choice: " choice + echo "$choice" + return 0 + done +} + +# ============================================ +# WFM Actions +# ============================================ +ensure_wfm_portman() { + local url="${1:-}" + if [[ -z "$url" ]]; then + read -p "Enter WFM URL: " url + fi + [[ -n "$url" ]] && run_cmd "$WFM_DIR" "Generating Postman-based collection using Portman..." bash run.sh portman "$url" +} + +wfm_1() { ensure_wfm_portman "${1:-}"; } +wfm_2() { + if [[ ! -f "$WFM_DIR/postman_collection.json" || ! -f "$WFM_DIR/newman-data/device-agent.env.json" || ! -f "$WFM_DIR/newman-data/device-agent.iteration.json" ]]; then + echo "Portman-generated collection is missing, generating it first..." + ensure_wfm_portman + fi + run_cmd "$WFM_DIR" "Running Newman against the current Postman-based collection..." bash run.sh newman +} +wfm_3() { read -p "Enter WFM URL: " url; [[ -n "$url" ]] && run_cmd "$WFM_DIR" "Generating Postman-based collection and running Newman..." bash run.sh all "$url"; } +wfm_4() { echo "Latest report:"; (cd "$WFM_DIR" && ls -lrt report_*.html 2>/dev/null | tail -1 || echo "No reports"); read -p "Press Enter..." _; } + +# ============================================ +# Device Actions +# ============================================ +dev_1() { run_cmd "$DEVICE_DIR" "Building..." make build; } +dev_2() { run_cmd "$DEVICE_DIR" "Starting server..." make run-server; } +dev_3() { run_cmd "$DEVICE_DIR" "Running tests..." make run-tests; } +dev_4() { run_cmd "$DEVICE_DIR" "Running demo..." make demo; } +dev_5() { run_cmd "$DEVICE_DIR" "Stopping server..." make kill-server; } +dev_6() { run_cmd "$DEVICE_DIR" "Cleaning..." make clean; } +dev_7() { echo "Latest report:"; (cd "$DEVICE_DIR/reports" && ls -lrt conformance-report-*.html 2>/dev/null | tail -1 || echo "No reports"); read -p "Press Enter..." _; } + +# ============================================ +# Persona Menus (Simplified) +# ============================================ +wfm_menu() { + while true; do + clear + echo "==============================" + echo " WFM Supplier" + echo "==============================" + echo " 1. Setup Portman" + echo " 2. Run Newman" + echo " 3. Setup + Run" + echo " 4. View Report" + echo " 5. Back" + echo + read -p "Enter choice: " choice + case "$choice" in + 1) wfm_1 ;; + 2) wfm_2 ;; + 3) wfm_3 ;; + 4) wfm_4 ;; + 5) return ;; + esac + done +} + +device_menu() { + while true; do + clear + echo "==============================" + echo " Device Supplier" + echo "==============================" + echo " 1. Build" + echo " 2. Start Server" + echo " 3. Run Tests" + echo " 4. Demo" + echo " 5. Stop Server" + echo " 6. Clean" + echo " 7. View Report" + echo " 8. Back" + echo + read -p "Enter choice: " choice + case "$choice" in + 1) dev_1 ;; + 2) dev_2 ;; + 3) dev_3 ;; + 4) dev_4 ;; + 5) dev_5 ;; + 6) dev_6 ;; + 7) dev_7 ;; + 8) return ;; + esac + done +} + +# ============================================ +# Main Menu +# ============================================ +main_menu() { + while true; do + clear + echo "==============================" + echo " Margo Conformance CLI" + echo "==============================" + echo " 1. WFM Supplier" + echo " 2. Device Supplier" + echo " 3. Exit" + echo + read -p "Enter choice: " choice + + case "$choice" in + 1) wfm_menu ;; + 2) device_menu ;; + 3) echo "Goodbye!"; exit 0 ;; + esac + done +} + +# ============================================ +# Start Here +# ============================================ +main_menu diff --git a/demo.md b/demo.md new file mode 100644 index 0000000..1dc477f --- /dev/null +++ b/demo.md @@ -0,0 +1,179 @@ +# Margo Conformance Test Suite — Demo Guide + +--- + +## 1. The one-paragraph version + +Margo is a spec that defines how a **device** (an edge machine running workloads) and a **WFM** (Workload Fleet Manager — the cloud/control-plane software that manages many devices) are supposed to talk to each other over HTTPS. This suite lets a vendor who built *either side* prove their implementation follows that spec correctly — without needing the other side's real system. We give them a trustworthy **mock** stand-in for whichever side they didn't build, run a battery of test calls, and hand back a pass/fail report. + +Two vendor situations, two personas: + +| Persona | The vendor brought... | We provide... | +|---|---|---| +| **Device Supplier** | A real device / device-agent | A mock WFM server to test it against | +| **WFM Supplier** | A real WFM (e.g. Eclipse Symphony) | A mock device that fires test calls at it | + +(There's also an **Application Supplier** persona for validating application packages.) + +--- + +## 2. The conversation both personas are testing + +Regardless of which side is "real" and which is "mock," every test is checking the same underlying conversation, because that conversation *is* the Margo spec: + +1. **Get the WFM's root certificate** — the device downloads the WFM's CA cert so it knows who it's talking to (`GET /onboarding/certificate`). +2. **Onboard** — the device introduces itself by sending its own certificate; the WFM registers it and hands back a `clientId` (`POST /onboarding`). Think of it like a new employee showing ID at security on day one — everything after this uses that badge. +3. **Report capabilities** — the device tells the WFM what it can run (hardware, OS, resources) (`POST/PUT /clients/{clientId}/capabilities`). +4. **Fetch desired state** — the device asks "what am I supposed to be running?" (`GET /clients/{clientId}/deployments`). +5. **Download the actual deployment content** — the device pulls the application bundle / deployment manifest referenced by the desired state (`GET .../bundles/{digest}`, `GET .../deployments/{id}/{digest}`). +6. **Report status** — the device reports back whether the deployment succeeded, failed, or is progressing (`POST /clients/{clientId}/deployments/{id}/status`). + +From step 3 onward, every request is **cryptographically signed** (RFC 9421 HTTP Message Signatures) using the device's certificate — so the WFM can verify it's really talking to the device it onboarded, not an impostor. + +Every test in this suite is really just: *"send one of these calls, in some circumstance (normal, or deliberately broken), and check the response is exactly what the spec says it should be."* + +--- + +## 3. Device Supplier persona + +**Who's real, who's mock:** the vendor's **device** is real. **mock WFM server** (a small Go program) plays the role of the WFM. + +**How they connect:** the real device is pointed at the mock WFM's URL (`https://:3001/v1alpha2/margo`) instead of a real WFM, and it runs through the exact 6-step conversation above. The mock WFM answers with real, spec-correct responses — including the *correct error* when the device does something wrong (missing signature → 401, bad certificate → 400, unknown/untrusted certificate → 403, malformed request body → 422, and so on). + +**What we're testing:** does the device's own client software correctly speak the protocol — right endpoints, right signing, right handling of both success *and* error responses? + +**How we're testing it, two ways:** +- **Fixed order** — the classic path: onboarding, then capabilities, then desired state, then deployment, then status-back, always in that order. This matches how a simple, well-behaved device would naturally proceed. +- **Flex (random) order** — after onboarding (which always has to be first — you can't report capabilities before you exist), the remaining calls fire in a *random* relative order each run. This proves the mock WFM doesn't secretly assume a fixed sequence, because a real device implementation is free to call capabilities, desired-state, and status-reporting in whatever order makes sense to it. Only onboarding is a hard prerequisite. + +**Groups — what they're for:** a *group* is just a named, curated bundle of test cases (e.g. `bronze`, `gold`, `flex-order`) so you can run a targeted subset instead of everything at once — useful for tiering (bronze/silver/gold conformance levels), or isolating a particular test style. A group is one folder containing a `group.json` (name, version, description, which test-case IDs belong to it) plus the test-case files it references. + +**Commands:** + +```bash +cd conformance + +# 1) Create / prepare test data and groups +./conformance.sh + → 2 (Device Supplier) + → create a new group, or select an existing one + +# (non-interactive equivalent) +./conformance.sh device "/path/to/test-scenarios.json" + +# 2) Run the tests for a group +./run-tests.sh + → 2 (Device Supplier) + → pick a group (e.g. bronze, flex-order) + → point it at the mock WFM URL (or the vendor's real WFM, if testing the reverse direction) + +# (non-interactive equivalent) +./run-tests.sh device bronze + +# Report lands in: +conformance/Runner/device-supplier/conformance-report-.html +``` + +--- + +## 4. WFM Supplier persona + +**Who's real, who's mock:** the vendor's **WFM** is real (e.g. an Eclipse Symphony instance). Our **mock device** plays the role of the device. + +**What "mock device" actually is:** it's not a separate server — it's a script (`run_wfm_scenarios.js`) that *acts as* a device. It has its own certificate and private key, computes real RFC 9421 signatures, and fires the same 6-step conversation — but now *we're* the one initiating calls, against the vendor's real WFM URL. + +**How they connect:** you give the script the vendor's real WFM URL (e.g. `https://symphony.machine:8082/v1alpha2/margo`), and it runs through onboarding → capabilities → desired state → bundle/manifest download → status report, exactly like a real device would, including deliberately-broken variants (skip the signature, send a bad digest, send garbage certificate data, ask for a non-existent deployment) to confirm the WFM rejects those correctly too. + +**What we're testing:** does the vendor's WFM implementation correctly accept valid device onboarding, validate certificates and signatures, serve capabilities/desired-state/bundles/manifests correctly, record status reports, and return the *right* error code for the *right* reason? + +**How we're testing it:** the test data (a Postman-style collection) documents, for every endpoint, both a success example and every documented error example. The script turns each documented example into an actual HTTP call engineered to trigger that exact condition, sends it, and compares the real response against what's expected. Some checks intentionally allow more than one correct answer (e.g. both 400 and 401 are reasonable ways for different implementations to say "bad request") — that flexibility is explicit and documented, never silently applied. + +**Groups — what they're for:** same idea as the device side — a named bundle of specific test-case IDs from a Postman collection (e.g. `bronze grp`, `silver`, `diamond`) so you can run a targeted subset. + +**Commands:** + +```bash +cd conformance + +# 1) Create / prepare test data and groups +./conformance.sh + → 1 (WFM Supplier) + → 1 OpenAPI spec based (generate tests from an OpenAPI spec), or + → 2 Functional tests (group-based, from a Postman collection) + → create a new group, or select an existing one + +# (non-interactive equivalent) +./conformance.sh wfm openapi /path/to/openapi.yaml + +# 2) Run the tests for a group, against the vendor's real WFM +./run-tests.sh + → 1 (WFM Supplier) + → pick a group (e.g. "bronze grp") + → enter the vendor's real WFM Server URL + +# (non-interactive equivalent) +./run-tests.sh wfm "bronze grp" https://symphony.machine:8082/v1alpha2/margo + +# Report lands in: +conformance/Runner/wfm-supplier/wfm-scenario-report-_.html +``` + +--- + +## 5. Why should a client trust this suite? + +1. **We test our own mock against itself first.** Before we ever point this at a client's real system, our own simulated device runs the *entire* fixed-order suite against our own mock WFM, and it has to pass 100%. That proves our reference implementation of "correct spec behavior" actually is correct and self-consistent, on both sides we control. +2. **Every expected outcome traces back to the spec, not to what's convenient.** Each test step encodes an exact expected status code and response shape taken from the Margo API definition — not something invented ad hoc. +3. **We test failure paths, not just the happy path.** A big share of the test set is deliberately-broken requests: missing signature, wrong certificate, tampered digest, malformed body. A system that only ever gets the happy path right isn't actually spec-conformant — correctly *rejecting* bad input is just as important, and this suite checks that explicitly on both personas. +4. **The exact same rules apply whether we're testing our own mock or a client's real system.** There's no special leniency mode for "friendly" tests — the same pass/fail logic, the same expected codes, run either way. When we find a gap (like we did earlier today — a certificate validation gap in our own mock's onboarding), we fix it the same way we'd expect a vendor to fix theirs. +5. **Reports are generated from real evidence, not manual sign-off.** Every row in the report is a real HTTP request that was actually sent and a real response that was actually received, with the expected vs. actual value shown side by side — it's an auditable trail, not a checklist someone filled in by hand. + +--- + +## 6. Command cheat sheet + +```bash +cd conformance + +# Create test data / groups (CLI #1) +./conformance.sh # interactive +./conformance.sh device # device supplier, direct +./conformance.sh wfm openapi # wfm supplier, direct + +# Run tests (CLI #2) +./run-tests.sh # interactive +./run-tests.sh device # device supplier, direct +./run-tests.sh wfm # wfm supplier, direct +./run-tests.sh help # full built-in help text +``` + +--- + +## 7. Anticipated questions (FAQ) + +**"What's a mock server / mock device, in plain terms?"** +A stand-in that behaves exactly like the real thing is supposed to, per spec, so you can test the other side in isolation. Mock WFM = a fake-but-correct cloud manager. Mock device = a script that behaves exactly like a real, well-behaved (and occasionally deliberately misbehaving) device. + +**"Why do I need groups — why not just run everything?"** +You often want a smaller, targeted run — e.g. only the tests relevant to a conformance tier, or only the tests for one feature you just changed — instead of the full suite every time. Groups also let you organize by intent (fixed-order vs. flex-order, bronze vs. gold tier, etc.). + +**"What happens if a real device or WFM fails a test?"** +The report shows exactly which step failed, what was expected, and what was actually returned — enough detail for the vendor to go fix the specific gap, not just "something's wrong." + +**"What's the difference between the fixed-order and flex-order tests?"** +Fixed-order assumes the classic, predictable call sequence. Flex-order proves the system under test doesn't *require* that exact sequence beyond "onboarding must come first" — because real devices may legitimately call things in a different order. + +**"Is this testing security too, or just functionality?"** +Both. Signature verification, certificate validation, and rejection of untrusted/malformed input are core parts of the test set. + +**"Do I need my own real device or WFM to see this work?"** +No — for the demo, both personas can be run entirely against our own mock implementations, so you can see the full flow, the groups, and the reports without needing a live third-party system. + +**"How long does a run take?"** +Seconds to few minutes, depending on the group size — this is direct HTTP calls, not a slow end-to-end environment spin-up. + +**"What do I actually get at the end?"** +A self-contained HTML report per run: pass/fail counts, every step's expected vs. actual result, and (for WFM Supplier runs) which real WFM URL was tested — saved under `Runner//`. + +**"Can I test just one thing, like only onboarding?"** +Yes — both CLIs support running a single group, and the device-supplier runner also supports filtering to a single scenario or even a single step via flags, for focused debugging. diff --git a/device-supplier/Final-Summary.md b/device-supplier/Final-Summary.md new file mode 100644 index 0000000..ef86f22 --- /dev/null +++ b/device-supplier/Final-Summary.md @@ -0,0 +1,1227 @@ +# Margo Device Supplier Conformance Suite — Complete Guide + +**Version:** 1.0 (June 2026) +**API Spec:** Margo Management Interface v1.0.0 + +--- + +## What Is This Suite? + +This is a **conformance testing framework** for the **Device Supplier** persona in the Margo ecosystem. Its job is to verify that a real device-agent correctly implements the Margo Management Interface API by testing it against a mock WFM (Workload Fleet Manager) server. + +**Who uses it:** A Margo vendor who has built a device-agent and wants to verify it behaves correctly before connecting it to a real WFM. + +**What it does:** +- Runs a mock WFM server that enforces the full Margo Management Interface spec +- Accepts connections from any device-agent implementation +- Validates every API call the device-agent makes against a rulebook (`assertions.json`) +- Reports pass/fail per test step + +**Important: You do NOT need to write any Go code.** The test-scenarios are plain JSON files you create following a template. The mock server reads validation rules from `assertions.json` — all data-driven, no compilation needed to add or change tests. + +--- + +## Architecture + +``` + ┌──────────────────────────────────┐ + │ MOCK WFM SERVER (bin/server) │ + │ https://localhost:3001 │ + │ │ + YOUR DEVICE-AGENT ────►│ Validates requests against │ + (real device, the │ assertions.json rulebook │ + thing being tested) │ │ + │ ✓ RFC 9421 signature check │ + │ ✓ Content-Digest check │ + │ ✓ Schema validation │ + └──────────────────────────────────┘ + │ + ▼ + Reports / Logs + +───────── Additionally, for scripted testing: ───────── + + ┌──────────────────────────────────────┐ + │ MOCK DEVICE-AGENT (bin/run_tests) │ + │ Reads test-scenarios.json │ + │ Sends scripted API calls │ + │ Validates responses │ + └──────────────────────────────────────┘ + ↑ + Your test-scenarios.json + (custom format, explained below) +``` + +**Two ways to run conformance tests:** + +| Method | When to use | How | +|--------|-------------|-----| +| **Scripted (run_tests.go)** | Verify mock server works; automate specific API call sequences | Write test-scenarios.json → `make demo` | +| **Real device-agent** | Test your actual device-agent implementation | Start mock server → connect your device-agent | + +The **recommended real-world workflow** is: use the Data-Generator CLI to register your test scenarios, then use the Runner CLI to start the mock server and run tests. Your real device-agent connects to the mock server for actual conformance testing. + +--- + +## Directory Layout + +``` +conformance/ +├── conformance.sh CLI #1 — Data-Generator +├── run-tests.sh CLI #2 — Runner +│ +├── Data-Generator/ +│ └── device-supplier/ +│ ├── assertions.json Validation rulebook (server copy) +│ ├── test-scenarios.json Active test scenarios +│ └── groups/ Test groups +│ ├── gold/ +│ │ ├── group.json Which test IDs belong to this group +│ │ └── test-scenarios.json +│ └── silver/ +│ └── ... +│ +└── device-supplier/ Mock WFM server source + ├── Makefile Build + run commands + ├── run_tests.go Mock device-agent (internal use) + ├── manifests/ + │ └── assertions.json Server validation rulebook (authoritative) + ├── device-scenarios/ + │ └── test-scenarios.json Active test scenarios for run_tests + ├── certs/ TLS certificates + │ ├── ca-cert.pem Root CA — give this to your real device-agent + │ ├── server-cert.pem Mock WFM server TLS cert + │ ├── device-cert.pem Demo device cert (used by run_tests.go) + │ └── device-key.pem Demo device key (used by run_tests.go) + ├── bin/ + │ ├── server Built mock WFM server binary + │ └── run_tests Built mock device-agent binary + └── reports/ + └── conformance-report-*.html +``` + +--- + +## Prerequisites + +| Requirement | Check | +|-------------|-------| +| Go 1.20+ | `go version` | +| `jq` | `jq --version` | +| `openssl` | `openssl version` | +| `make` | `make --version` | + +--- + +## Part 1 — Create Your Test Scenarios + +### The Custom Format + +Margo vendors create their test scenarios as a **custom JSON array** following this format. This is NOT Postman, NOT pytest, NOT any external framework — it is a purpose-built format parsed directly by the mock device-agent runner. + +**Start from this template — copy it and fill in your own values:** +``` +conformance/device-supplier/device-scenarios/TEMPLATE_custom_test_scenario.json +``` + +This file contains four ready-to-use scenario skeletons covering every Margo endpoint (onboarding, capabilities, deployments, bundle download, status reporting, and negative tests). Copy it, rename it to something like `my-device-test-scenarios.json`, and replace the placeholder values with your device's details. + +> `test-scenarios.json` in the same folder is the full reference implementation — it is the complete working test suite used by the conformance runner. Use the **TEMPLATE** file, not `test-scenarios.json`, as your starting point. + +### Top-Level Structure + +Your file must be a **JSON array of scenario objects**: + +```json +[ + { + "id": "scenario-my-device-onboarding", + "name": "Device Onboarding", + "description": "Tests the onboarding flow for my device", + "steps": [ ... ] + }, + { + "id": "scenario-my-device-capabilities", + "name": "Capability Reporting", + "description": "Tests capability POST/PUT", + "steps": [ ... ] + } +] +``` + +Scenarios run **top to bottom**. Each scenario is independent — variables do not leak between scenarios. + +--- + +### The 8 Margo Endpoints You Can Test + +Every step's `endpoint` must be one of these. Anything else returns 404. + +| # | Method | Endpoint | Purpose | Auth required? | +|---|--------|----------|---------|----------------| +| 1 | GET | `/api/v1/onboarding/certificate` | Fetch the WFM root CA certificate | No | +| 2 | POST | `/api/v1/onboarding` | Register device — receive `clientId` | No (bootstrap) | +| 3 | POST | `/api/v1/clients/{clientId}/capabilities` | Report device hardware + roles | Yes (sign) | +| 4 | PUT | `/api/v1/clients/{clientId}/capabilities` | Update device hardware + roles | Yes (sign) | +| 5 | GET | `/api/v1/clients/{clientId}/deployments` | Get deployment manifest | Yes (sign) | +| 6 | GET | `/api/v1/clients/{clientId}/bundles/{digest}` | Download deployment bundle tarball | Yes (sign) | +| 7 | GET | `/api/v1/clients/{clientId}/deployments/{deploymentId}/{digest}` | Get individual deployment manifest | Yes (sign) | +| 8 | POST | `/api/v1/clients/{clientId}/deployments/{deploymentId}/status` | Report deployment status | Yes (sign) | + +> `{clientId}`, `{digest}`, `{deploymentId}` are placeholder tokens — the runner substitutes values you save with `extract_context` from earlier steps. + +"Auth required" means the request must carry a valid RFC 9421 HTTP signature. The runner signs automatically unless you set `"skip_signing": true`. + +--- + +### Valid Field Values + +Use these exact values in your request bodies to pass validation. Any other value returns 422. + +**Onboarding request:** +```json +"apiVersion": "onboarding.margo.org/v1alpha1" +"kind": "OnboardingRequest" +``` + +**Capabilities manifest:** +```json +"apiVersion": "device.margo.org/v1alpha1" +"kind": "DeviceCapabilitiesManifest" +``` + +Valid `properties.roles` values (must have at least one): +``` +"Standalone Cluster" "Cluster Leader" "Standalone Device" +``` + +Valid `resources.cpu.architecture` values: +``` +"amd64" "x86_64" "arm64" "arm" +``` + +Valid `resources.interfaces[*].type` values: +``` +"ethernet" "wifi" "cellular" "bluetooth" "usb" "canbus" "rs232" +``` + +**Deployment status report:** +```json +"apiVersion": "deployment.margo.org/v1alpha1" +"kind": "DeploymentStatusManifest" +``` + +Valid `status.state` and `components[*].state` values: +``` +"pending" "installing" "installed" "failed" "removing" "removed" +``` + +--- + +### Step Object — Full Schema + +```json +{ + "id": "step-1.1", + "name": "Onboard My Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { "field": "clientId", "operation": "exists" } + ], + "extract_context": { + "clientId": "clientId" + }, + "skip_signing": false, + "skip_certificate_injection": false +} +``` + +#### All Step Fields + +| Field | Required | Type | Description | +|-------|----------|------|-------------| +| `id` | Yes | string | Unique step ID. Use format `step-X.Y` (e.g., `step-1.1`, `step-2.3`). Referenced in group.json. | +| `name` | Yes | string | Human-readable name shown in reports | +| `method` | Yes | string | HTTP verb: `"GET"`, `"POST"`, or `"PUT"` | +| `endpoint` | Yes | string | URL path, without base URL. Supports `{placeholder}` substitution | +| `request_body` | No | object | JSON body for POST/PUT. Omit for GET requests | +| `headers` | No | object | Extra HTTP headers. Values support `{placeholder}` substitution | +| `expected_status` | Yes | number | Expected HTTP status code. Any other code → FAIL | +| `validations` | No | array | Checks to run on the response body/headers | +| `extract_context` | No | object | Save response values as named variables for later steps | +| `skip_signing` | No | bool | Default `false`. Set `true` to skip RFC 9421 signature (for unsigned-request rejection tests) | +| `skip_certificate_injection` | No | bool | Default `false`. Set `true` to send the `certificate` string as-is without loading from a file path | + +### Validations — Checking the Response + +```json +"validations": [ + { "field": "clientId", "operation": "exists" }, + { "field": "status", "operation": "equals", "value": "capabilities_received" }, + { "field": "error", "operation": "contains", "value": "certificate" }, + { "field": "certificate", "operation": "not_empty" }, + { "field": "deployments", "operation": "is_array" }, + { "field": "_headers.ETag", "operation": "not_empty" } +] +``` + +#### Validation Operations + +| Operation | `value` field needed? | Passes when | +|-----------|----------------------|-------------| +| `exists` | No | Field is present (any value, even empty) | +| `not_empty` | No | Field is present and not `""`, `null`, or `[]` | +| `equals` | Yes | Field value matches `value` exactly | +| `contains` | Yes | Field value (string) contains `value` as a substring | +| `is_string` | No | Field value is a JSON string | +| `is_number` | No | Field value is a JSON number | +| `is_array` | No | Field value is a JSON array | +| `is_object` | No | Field value is a JSON object | + +#### Field Path Syntax + +| Path | Accesses | +|------|---------| +| `"clientId"` | Top-level JSON field | +| `"status.state"` | Nested field | +| `"deployments.0.deploymentId"` | First array element's field | +| `"_headers.ETag"` | HTTP response header (`_headers.` prefix) | + +### Context — Passing Data Between Steps + +`extract_context` saves a value from one step's response. Saved values can be injected as `{placeholders}` in later steps within the same scenario. + +**Save a value:** +```json +"extract_context": { + "clientId": "clientId", + "manifestEtag": "_headers.ETag", + "deploymentId": "deployments.0.deploymentId" +} +``` + +Left side = your variable name. Right side = JSON path in the response. + +**Use a saved value:** +```json +"endpoint": "/api/v1/clients/{clientId}/capabilities", + +"headers": { + "If-None-Match": "{manifestEtag}" +}, + +"request_body": { + "deploymentId": "{deploymentId}" +} +``` + +Placeholders work in: `endpoint`, `headers` values, and string values inside `request_body`. + +### Certificate Handling + +The `certificate` field in `request_body` has special handling: + +**Load from file (positive tests):** +```json +"request_body": { + "certificate": "./certs/device-cert.pem" +} +``` +The runner detects the `./certs/` prefix and reads the PEM file. Actual cert content is sent. + +**Use a literal string (rejection tests):** +```json +"request_body": { + "certificate": "rnd-key-7f3a91b2c4d8e6" +}, +"skip_certificate_injection": true +``` +The literal string is sent as-is. The server's rejection list blocks it with 403. + +--- + +### Common Test Patterns + +Every scenario that needs a `clientId` must onboard first. Use a setup step at the start: + +```json +{ + "id": "step-1.0", + "name": "Onboard Device (Setup)", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [], + "extract_context": { "clientId": "clientId" }, + "skip_signing": false +} +``` + +**Pattern A — Positive test (expect the call to succeed):** +```json +{ + "id": "step-1.1", + "name": "Report Capabilities", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "my-device", + "vendor": "My Vendor", + "modelNumber": "MODEL-001", + "serialNumber": "SN-12345", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "amd64" }, + "memory": "8Gi", + "storage": "128Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 201, + "validations": [], + "extract_context": {}, + "skip_signing": false +} +``` + +**Pattern B — Validation error test (expect 422 for bad field value):** + +Change any value to something invalid (wrong role, wrong architecture, empty array) and expect 422: +```json +{ + "id": "step-2.1", + "name": "Reject Invalid Role", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "my-device", "vendor": "My Vendor", + "modelNumber": "MODEL-001", "serialNumber": "SN-12345", + "roles": ["NotAValidRole"], + "resources": { + "cpu": { "cores": 4, "architecture": "amd64" }, + "memory": "8Gi", "storage": "128Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 422, + "validations": [{ "field": "errors", "operation": "is_array" }], + "extract_context": {}, + "skip_signing": false +} +``` + +Other things that trigger 422: empty `roles` array, unknown `architecture`, unknown `interface.type`, missing required field, invalid `status.state` in a status report. + +**Pattern C — Signature rejection test (expect 401):** + +Set `"skip_signing": true` to send the request without a signature: +```json +{ + "id": "step-2.2", + "name": "Reject Unsigned Capabilities", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { ... }, + "headers": {}, + "expected_status": 401, + "validations": [{ "field": "error", "operation": "exists" }], + "extract_context": {}, + "skip_signing": true +} +``` + +**Pattern D — Schema error test (expect 400):** + +Send a request with missing required fields or wrong `apiVersion`/`kind`: +```json +{ + "id": "step-2.3", + "name": "Reject Missing Certificate", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest" + }, + "headers": {}, + "expected_status": 400, + "validations": [{ "field": "error", "operation": "exists" }], + "extract_context": {}, + "skip_signing": false +} +``` + +Other things that trigger 400: missing `Content-Digest` header on a POST/PUT (add header `"Content-Digest": ""` and omit the body hash), wrong or missing `kind`. + +**Pattern E — ETag caching test (expect 304):** + +Save the `ETag` from a GET response, then send it back with `If-None-Match`: +```json +{ + "id": "step-3.1", + "name": "Get Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { "Accept": "application/vnd.margo.manifest.v1+json" }, + "expected_status": 200, + "validations": [], + "extract_context": { "manifestEtag": "_headers.ETag" }, + "skip_signing": false +}, +{ + "id": "step-3.2", + "name": "Get Deployments — Cached (should return 304)", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json", + "If-None-Match": "{manifestEtag}" + }, + "expected_status": 304, + "validations": [], + "extract_context": {}, + "skip_signing": false +} +``` + +--- + +### Complete Example: Onboarding → Capabilities → Deployment + +```json +[ + { + "id": "scenario-vendor-happy-path", + "name": "Vendor Happy Path", + "description": "Full onboarding, capabilities, and deployment status flow", + "steps": [ + { + "id": "step-1.0", + "name": "Onboard Device", + "method": "POST", + "endpoint": "/api/v1/onboarding", + "request_body": { + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "./certs/device-cert.pem" + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { "field": "clientId", "operation": "exists" } + ], + "extract_context": { + "clientId": "clientId" + } + }, + { + "id": "step-1.1", + "name": "Report Capabilities", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/capabilities", + "request_body": { + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "vendor-device-001", + "vendor": "Vendor Corp", + "modelNumber": "VC-1000", + "serialNumber": "SN-ABC123", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "arm64" }, + "memory": "8Gi", + "storage": "64Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } + }, + "headers": {}, + "expected_status": 201, + "validations": [ + { "field": "status", "operation": "equals", "value": "capabilities_received" } + ], + "extract_context": {} + }, + { + "id": "step-1.2", + "name": "Get Deployments", + "method": "GET", + "endpoint": "/api/v1/clients/{clientId}/deployments", + "headers": { + "Accept": "application/vnd.margo.manifest.v1+json" + }, + "expected_status": 200, + "validations": [ + { "field": "deployments", "operation": "is_array" }, + { "field": "_headers.ETag", "operation": "exists" } + ], + "extract_context": { + "deploymentId": "deployments.0.deploymentId" + } + }, + { + "id": "step-1.3", + "name": "Post Status", + "method": "POST", + "endpoint": "/api/v1/clients/{clientId}/deployments/{deploymentId}/status", + "request_body": { + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "{deploymentId}", + "status": { "state": "installed" }, + "components": [ + { "name": "my-app", "state": "installed" } + ] + }, + "headers": {}, + "expected_status": 200, + "validations": [ + { "field": "acknowledgement", "operation": "equals", "value": "received" } + ], + "extract_context": {} + } + ] + } +] +``` + +### Quick Reference: Which Status Code to Expect? + +| Endpoint | Success | Invalid body | No signature | Cert blocked | Wrong digest / client | +|----------|---------|-------------|-------------|-------------|----------------------| +| GET /onboarding/certificate | 200 | — | — | — | — | +| POST /onboarding | 201 | 400 | — (not required) | 403 | — | +| POST /capabilities | 201 | 422 | 401 | — | 404 (unknown clientId) | +| PUT /capabilities | 201 | 422 | 401 | — | 404 (unknown clientId) | +| GET /deployments | 200 / 304 | 406 (wrong Accept header) | 401 | — | 404 (unknown clientId) | +| GET /bundles/{digest} | 200 / 304 | — | 401 | — | 404 (wrong digest) | +| GET /deployments/{id}/{digest} | 200 / 304 | — | 401 | — | 404 (wrong digest) | +| POST /status | 200 | 422 | 401 | — | 422 (deploymentId mismatch) | + +--- + +## Part 2 — Register Scenarios with Data-Generator + +The **Data-Generator** (`conformance.sh`) organises your test-scenarios.json files into named groups. Groups let you run targeted subsets of tests. + +### What It Does + +1. You place your `test-scenarios.json` file(s) in a folder +2. Run `conformance.sh` (interactive CLI) +3. It reads all JSON files, extracts all step/scenario IDs, copies files to `Data-Generator/device-supplier/groups//` +4. Creates a `group.json` listing every test ID in that group + +The Runner CLI later reads from these groups to decide which scenarios to run. + +### Run the Data-Generator + +```bash +cd /home/margo/test/sandbox/conformance +bash conformance.sh +``` + +Follow the interactive prompts: +1. Select **Device Supplier** persona +2. Select or create a group (e.g., `myvendor`) +3. Point to your `test-scenarios.json` file + +The CLI creates: +``` +Data-Generator/device-supplier/groups/myvendor/ + ├── group.json # lists all test IDs extracted from your files + └── test-scenarios.json # copy of your file +``` + +### group.json Format + +```json +{ + "name": "myvendor", + "version": "1.0.0", + "persona": "device-supplier", + "description": "My vendor conformance scenarios", + "testCases": [ + "step-1.0", + "step-1.1", + "step-1.2", + "scenario-vendor-happy-path" + ] +} +``` + +The `testCases` array contains IDs that will be used to filter which steps/scenarios run. If no IDs match, ALL scenarios run (safe fallback). + +--- + +## Part 3 — Run Conformance Tests + +### Option A: Via Runner CLI (Recommended) + +The **Runner** (`run-tests.sh`) starts the mock WFM server, runs your test scenarios through the mock device-agent, then generates a report. + +```bash +cd /home/margo/test/sandbox/conformance +bash run-tests.sh +``` + +Follow the interactive prompts: +1. Select **Device Supplier** (option 2) +2. Select **Group-based test scenarios** (option 1) +3. Select your group (e.g., `myvendor`) + +The runner: +- Builds `bin/server` and `bin/run_tests` if not already built +- Starts `bin/server` (mock WFM) in background on `https://localhost:3001` +- Copies your scenarios from the group into `device-scenarios/test-scenarios.json` +- Runs `bin/run_tests` (mock device-agent) which reads the scenarios and fires API calls +- Stops the server and generates an HTML report in `reports/` + +### Option B: Via Makefile (Quick Demo) + +From the `device-supplier/` directory you can build and run directly: + +```bash +cd /home/margo/test/sandbox/conformance/device-supplier + +# Build both binaries +make build + +# Run full demo (starts server + runs tests + generates report) +make demo + +# Or step by step: +make run-server # Terminal 1 — start mock WFM server +make run-tests # Terminal 2 — run mock device-agent + +# Stop server +make kill-server +``` + +#### All Makefile Targets + +| Command | What it does | +|---------|-------------| +| `make build` | Build mock server (`bin/server`) and test runner (`bin/run_tests`) | +| `make build-server` | Build mock server only | +| `make build-tests` | Build test runner only | +| `make run-server` | Start mock WFM server in background on port 3001 | +| `make run-tests` | Run the mock device-agent against the server | +| `make demo` | Build → start server → run tests → show report path | +| `make kill-server` | Stop the running server | +| `make clean` | Remove `bin/` directory | + +--- + +## Part 4 — Test with Your Real Device-Agent + +This is the primary conformance test path. Your actual device-agent implementation connects to the mock WFM server. The mock server validates every request it receives. + +### Step 1: Build and Start the Mock WFM Server + +```bash +cd /home/margo/test/sandbox/conformance/device-supplier +make build +make run-server +``` + +The server starts on `https://localhost:3001`. Check it is running: +```bash +curl -k https://localhost:3001/health +``` + +### Step 2: Give Your Device-Agent the CA Certificate + +Your device-agent must trust the mock server's TLS certificate. Copy the mock server's CA cert to wherever your device-agent expects its trusted CA: + +```bash +# The mock server CA cert is at: +ls /home/margo/test/sandbox/conformance/device-supplier/certs/ca-cert.pem + +# Copy it to the device-agent's expected CA location +# (adjust destination path to match your device-agent config) +cp /home/margo/test/sandbox/conformance/device-supplier/certs/ca-cert.pem \ + ~/certs/ca-cert.pem +``` + +### Step 3: Generate Device Certificates (if needed) + +Use the `device-agent.sh` script to generate ECDSA device certificates (the format required by the Margo spec — P-256 curve): + +```bash +cd /home/margo/test/sandbox/scripts +sudo -E bash device-agent.sh +``` + +In the interactive menu: +1. Enter `1` to select **Docker** device type +2. Choose option `12` → **create_device_ecdsa_certs** + +This generates: +``` +~/certs/ + ├── device-ecdsa.key # ECDSA P-256 private key + └── device-ecdsa.crt # Self-signed device certificate +``` + +Copy these into your device-agent's certificate configuration directory and configure your device-agent to: +- Use `device-ecdsa.crt` as its device certificate (sent during onboarding) +- Use `device-ecdsa.key` to sign RFC 9421 HTTP requests + +### Step 4: Clear Device State (Required When Switching WFMs) + +> **Critical:** If your device-agent has previously connected to a real WFM, it stores a `clientId` locally. The mock WFM starts fresh with no clients registered — so the device will get a 404 on its first capabilities call and the test will fail. +> +> Always clear the device-agent's persisted data before switching to the mock WFM: + +```bash +# Stop the running device-agent container first +cd ~/sandbox/docker-compose +docker compose down + +# Delete the persisted onboarding state (forces fresh onboarding with mock WFM) +rm -rf ~/sandbox/docker-compose/data/ +``` + +The device-agent will now re-register from scratch with the mock WFM and get a new `clientId`. + +### Step 5: Start Your Device-Agent Against the Mock WFM + +The `device-agent.env` file sets `WFM_HOST=symphony.machine` (or your configured host). Override only the port so the agent connects to the mock WFM instead of the real one: + +```bash +# Start device-agent pointing at mock WFM port 3001 +WFM_PORT=3001 sudo -E bash /home/margo/test/sandbox/scripts/device-agent.sh docker start-docker +``` + +> **Note:** `WFM_HOST` comes from `device-agent.env` (already points to the correct host). Only `WFM_PORT` needs to be overridden from the default. Setting `WFM_PORT=3001` before the `sudo -E` call preserves it through the environment. + +Monitor device-agent logs: +```bash +sudo docker logs workload-fleet-management-client -f +``` + +### Step 6: Observe Results + +Watch the mock server logs to see what the device-agent sends and how the server responds: + +```bash +tail -f /tmp/wfm-server.log +``` + +A successful full flow looks like this in the device-agent logs: + +``` +INFO Starting device onboarding +INFO Preflight-http-request POST https://symphony.machine:3001/v1alpha2/margo/api/v1/onboarding +INFO Device onboarding successful {"deviceClientId": "ebf0e8d1-710b-4d92-a0ce-cca4d4c72576"} +INFO Device onboarded {"deviceId": "ebf0e8d1-..."} +INFO Starting capabilities reporting +INFO Preflight-http-request POST .../clients/ebf0e8d1-.../capabilities +INFO Capabilities reported successfully +INFO Workload Fleet Management Client started successfully +INFO Preflight-http-request GET .../clients/ebf0e8d1-.../deployments +INFO Bundle downloaded successfully +INFO Performing sync.... +INFO No change in desired and current states (304 Not Modified) ← polling working +``` + +And in the mock WFM server logs: + +``` +[Router] POST /v1alpha2/margo/api/v1/onboarding +[Router] POST /v1alpha2/margo/api/v1/clients/{clientId}/capabilities +[Router] GET /v1alpha2/margo/api/v1/clients/{clientId}/deployments +[Router] GET /v1alpha2/margo/api/v1/clients/{clientId}/bundles/{digest} +[Router] POST /v1alpha2/margo/api/v1/clients/{clientId}/deployments/{appId}/status +``` + +The mock server validates every request against `assertions.json`. Validation failures appear in the log as 400/401/422 responses with JSON error details. + +### Stop When Done + +```bash +cd /home/margo/test/sandbox/conformance/device-supplier +make kill-server +``` + +--- + +## API Reference — All 8 Endpoints + +Base URL: `https://localhost:3001/v1alpha2/margo` + +### 1. GET /api/v1/onboarding/certificate + +Retrieve the Root CA certificate. No authentication required. + +``` +→ Response 200: +{ "certificate": "-----BEGIN CERTIFICATE-----\n..." } +``` + +### 2. POST /api/v1/onboarding + +Register the device with the WFM. No signature required (bootstrap step — device has no key yet). + +```json +→ Request body: +{ + "apiVersion": "onboarding.margo.org/v1alpha1", + "kind": "OnboardingRequest", + "certificate": "" +} + +→ Response 201: +{ "clientId": "" } + +→ Response 400: invalid fields +{ "error": "field description" } + +→ Response 403: blocklisted certificate +{ "error": "Client rejected: ..." } +``` + +### 3. POST /api/v1/clients/{clientId}/capabilities + +Report device hardware capabilities. **RFC 9421 signature + Content-Digest required.** + +```json +→ Request body: +{ + "apiVersion": "device.margo.org/v1alpha1", + "kind": "DeviceCapabilitiesManifest", + "properties": { + "id": "device-001", + "vendor": "Vendor Corp", + "modelNumber": "MDL-100", + "serialNumber": "SN-12345", + "roles": ["Standalone Device"], + "resources": { + "cpu": { "cores": 4, "architecture": "arm64" }, + "memory": "8Gi", + "storage": "64Gi", + "interfaces": [{ "type": "ethernet" }], + "peripherals": [] + } + } +} + +→ Response 201: +{ "status": "capabilities_received" } + +→ Response 401: missing or invalid signature +→ Response 422: schema validation failure +{ "status": "validation_failed", "errors": [...] } +``` + +**Valid `roles` values:** `"Standalone Cluster"`, `"Cluster Leader"`, `"Standalone Device"` +**Valid `cpu.architecture` values:** `"amd64"`, `"x86_64"`, `"arm64"`, `"arm"` +**Valid `interfaces[*].type` values:** `"ethernet"`, `"wifi"`, `"cellular"`, `"bluetooth"`, `"usb"`, `"canbus"`, `"rs232"` +**Valid `peripherals[*].type` values:** `"gpu"`, `"display"`, `"camera"`, `"microphone"`, `"speaker"` + +### 4. PUT /api/v1/clients/{clientId}/capabilities + +Update device capabilities. Same body and rules as POST. **RFC 9421 signature required.** + +### 5. GET /api/v1/clients/{clientId}/deployments + +Retrieve the deployment manifest. **RFC 9421 signature required.** Must set `Accept: application/vnd.margo.manifest.v1+json`. + +``` +→ Response 200: manifest with ETags +→ Response 304: not modified (ETag match via If-None-Match) +→ Response 406: unsupported Accept header +``` + +### 6. GET /api/v1/clients/{clientId}/bundles/{digest} + +Download the deployment bundle. **RFC 9421 signature required.** Content-addressed: `{digest}` must match the server's bundle. + +``` +→ Response 200: tar.gz archive (Cache-Control: immutable) +→ Response 304: not modified +→ Response 404: digest not found +``` + +### 7. GET /api/v1/clients/{clientId}/deployments/{deploymentId}/{digest} + +Download a single deployment YAML. **RFC 9421 signature required.** + +``` +→ Response 200: YAML file (Cache-Control: immutable) +→ Response 304: not modified +→ Response 404: not found +``` + +### 8. POST /api/v1/clients/{clientId}/deployments/{deploymentId}/status + +Report deployment status. **RFC 9421 signature + Content-Digest required.** + +```json +→ Request body: +{ + "apiVersion": "deployment.margo.org/v1alpha1", + "kind": "DeploymentStatusManifest", + "deploymentId": "", + "status": { "state": "installed" }, + "components": [ + { "name": "app-component", "state": "installed" } + ] +} + +→ Response 200: +{ "acknowledgement": "received" } + +→ Response 422: invalid state or missing fields +``` + +**Valid `status.state` values:** `"pending"`, `"installing"`, `"installed"`, `"failed"`, `"removing"`, `"removed"` + +--- + +## RFC 9421 HTTP Signatures + +All write endpoints (POST/PUT capabilities, POST status) and all authenticated GET endpoints require HTTP Message Signatures per [RFC 9421](https://www.rfc-editor.org/rfc/rfc9421). + +**How the mock server verifies:** +1. Checks `Content-Digest` header matches SHA-256 of the request body → 400 if mismatch +2. Verifies `Signature` header using the device's public key from the onboarding certificate → 401 if invalid + +**What your device-agent must sign:** `@method`, `@target-uri`, and `content-digest` (for body requests). + +**Key format:** ECDSA P-256 in IEEE P1363 format (not DER). + +--- + +## Validation Rules Reference (assertions.json) + +The mock server loads `manifests/assertions.json` at startup. All validation is data-driven — change the file and restart the server to change what gets validated. No Go code changes needed. + +### Rule Structure + +```json +{ + "rule_id": "capabilities-008", + "field": "properties.roles", + "type": "array", + "required": true, + "minItems": 1, + "itemsType": "string", + "itemsEnum": ["Standalone Cluster", "Cluster Leader", "Standalone Device"], + "description": "properties.roles must contain at least one valid Margo device role" +} +``` + +| Field | Meaning | +|-------|---------| +| `rule_id` | Unique ID. Returned in error responses so you know which rule failed | +| `field` | JSON path to the field (dot notation; `*` wildcard for array items) | +| `type` | `"string"`, `"number"`, `"object"`, or `"array"` | +| `required` | If `true`, request is rejected when field is absent | +| `value` | Field must exactly equal this value | +| `enum` | Field value must be one of these strings | +| `minLength` | For strings: minimum character count | +| `minItems` | For arrays: minimum item count | +| `itemsType` | For arrays: each item must be this type | +| `itemsEnum` | For arrays: each item must be one of these values | + +### Error Response Formats + +| Scenario | Status | Body | +|----------|--------|------| +| Missing/invalid field (onboarding) | 400 | `{ "error": "field is required" }` | +| Schema validation failure (capabilities, status) | 422 | `{ "status": "validation_failed", "errors": [{ "rule_id": "...", "error": "..." }] }` | +| Invalid/missing signature | 401 | `{ "error": "Signature verification failed" }` | +| Body tampered (digest mismatch) | 400 | `{ "error": "content-digest header missing or invalid" }` | +| Blocklisted certificate | 403 | `{ "error": "Client rejected: ..." }` | +| Unknown client ID | 404 | `{ "error": "Client not found" }` | + +### How to Add a Validation Rule + +1. Open `manifests/assertions.json` +2. Find the endpoint block (e.g., `POST_capabilities`) +3. Add your rule to the `validations` array: + +```json +{ + "rule_id": "capabilities-019", + "field": "properties.firmwareVersion", + "type": "string", + "required": true, + "minLength": 1, + "description": "properties.firmwareVersion is required" +} +``` + +4. Restart the server (rules are loaded at startup): +```bash +make kill-server +make run-server +``` + +--- + +## Environment Variables + +### Mock Server (`bin/server`) + +| Variable | Default | Purpose | +|----------|---------|---------| +| `KEEP_DATA` | not set | Set to `true` to preserve `data/clients.json` and `data/deployments.json` between restarts | + +```bash +KEEP_DATA=true ./bin/server +``` + +### Mock Device-Agent (`bin/run_tests`) + +| Variable | Default | Purpose | +|----------|---------|---------| +| `DEVICE_PRIVATE_KEY_PATH` | `./certs/device-key.pem` | Path to device ECDSA private key | +| `DEVICE_CERTIFICATE_PATH` | `./certs/device-cert.pem` | Path to device certificate | + +```bash +DEVICE_PRIVATE_KEY_PATH=~/certs/device-ecdsa.key \ +DEVICE_CERTIFICATE_PATH=~/certs/device-ecdsa.crt \ +./bin/run_tests +``` + +--- + +## Validate Your JSON File + +Before submitting your `test-scenarios.json` to the Data-Generator, validate it: + +```bash +# Check syntax +jq empty my-test-scenarios.json && echo "Valid JSON" + +# Check structure — should print an array of scenario names +jq '.[].name' my-test-scenarios.json + +# Count scenarios and total steps +jq '[.[] | .steps | length] | add' my-test-scenarios.json + +# List all step IDs +jq '[.[].steps[].id]' my-test-scenarios.json +``` + +--- + +## Troubleshooting + +**"Server not responding" or connection refused** +```bash +# Check if server is running +ps aux | grep bin/server +# Or restart: +make kill-server && make run-server +# Check server log: +tail -50 /tmp/wfm-server.log +``` + +**404 on POST /capabilities — "Client not found"** +- Your device-agent stored a `clientId` from a previous WFM session and skipped onboarding +- The mock WFM starts fresh on every run and has no record of that `clientId` +- Fix: stop the device-agent, clear its persisted state, then restart: + ```bash + cd ~/sandbox/docker-compose + docker compose down + rm -rf data/ + WFM_PORT=3001 sudo -E bash /path/to/device-agent.sh docker start-docker + ``` + +**401 Unauthorized on POST /capabilities or POST /status** +- Your device-agent's signing key does not match the certificate submitted at onboarding +- The mock server stores the public key from `POST /onboarding` and uses it to verify signatures +- Ensure the same key pair is used for both + +**400 Bad Request: "content-digest header missing or invalid"** +- Your device-agent must compute `SHA-256` of the request body and set the `Content-Digest` header: + `Content-Digest: sha-256=::` + +**422 Validation errors** +- The response body contains `"errors": [{ "rule_id": "...", "error": "..." }]` +- Cross-reference the `rule_id` against `manifests/assertions.json` to see which field failed + +**403 Forbidden: "Client rejected"** +- The certificate submitted at onboarding is in the `rejected_certificates` blocklist in `assertions.json` +- Use a different certificate + +**Reports directory not found** +- Run from the `device-supplier/` directory: `cd conformance/device-supplier` +- The `reports/` directory is created automatically on first test run + +**Go build permission errors on module cache** +```bash +# Use a custom cache directory: +GOPATH=/tmp/go-build GOCACHE=/tmp/go-cache make build +``` + +**jq: invalid JSON** +```bash +# Find exactly where the error is: +python3 -m json.tool my-test-scenarios.json +``` + +--- + +## End-to-End Workflow Summary + +``` +1. CREATE TEST SCENARIOS + └── Draft my-test-scenarios.json following the template above + └── Validate: jq empty my-test-scenarios.json + +2. REGISTER WITH DATA-GENERATOR + └── cd conformance/ + └── bash conformance.sh + └── Select Device Supplier → create/select group → point to your file + └── Result: Data-Generator/device-supplier/groups// + +3a. RUN VIA RUNNER CLI (uses mock device-agent) + └── bash run-tests.sh + └── Select Device Supplier → Group-based → your group + └── Mock server starts → mock device-agent runs your scenarios → report generated + +3b. RUN WITH YOUR REAL DEVICE-AGENT + └── cd conformance/device-supplier/ + └── make run-server + └── Copy certs/ca-cert.pem to your device-agent's trusted CA location + └── Generate device certs: sudo -E bash ~/test/sandbox/scripts/device-agent.sh → option 12 + └── Configure device-agent WFM_HOST=localhost, WFM_PORT=3001 + └── Start device-agent → watch /tmp/wfm-server.log for results + └── make kill-server when done +``` + +--- + +*Last updated: June 2026 | Margo Management Interface API v1.0.0 | Device Supplier Conformance Suite* diff --git a/device-supplier/LICENSE b/device-supplier/LICENSE new file mode 100644 index 0000000..0149fe9 --- /dev/null +++ b/device-supplier/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Margo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/device-supplier/Makefile b/device-supplier/Makefile new file mode 100644 index 0000000..d18c9fe --- /dev/null +++ b/device-supplier/Makefile @@ -0,0 +1,106 @@ +.PHONY: help build-server build-tests build clean test demo run-tests run-custom-tests run-server kill-server + +help: + @echo "Device Supplier Conformance Suite - Make Commands" + @echo "" + @echo "Usage: make [target]" + @echo "" + @echo "Targets:" + @echo " build-server Build mock WFM server" + @echo " build-tests Build test runner" + @echo " build Build both server and test runner" + @echo " run-server Start mock WFM server (background)" + @echo " run-tests Run default conformance tests (device-scenarios/test-scenarios.json)" + @echo " run-custom-tests Run vendor scenarios: make run-custom-tests FILE=device-scenarios/my-file.json" + @echo " demo Full demo: start server, run tests, show report" + @echo " kill-server Stop the running server" + @echo " clean Remove all build artifacts" + @echo "" + +# Build targets +build-server: + @echo "📦 Preparing mock WFM server..." + @mkdir -p bin + @if [ ! -f bin/server ]; then \ + echo "Building from source..."; \ + go build -o bin/server ./cmd/device-supplier; \ + else \ + echo "✅ Server binary already exists: bin/server"; \ + fi + +build-tests: + @echo "📦 Preparing test runner..." + @mkdir -p bin + @if [ ! -f bin/run_tests ]; then \ + echo "Building from source..."; \ + go build -o bin/run_tests run_tests.go; \ + else \ + echo "✅ Test runner binary already exists: bin/run_tests"; \ + fi + +build: build-server build-tests + @echo "✅ All binaries built successfully" + +# Run targets +run-server: build-server + @echo "🚀 Starting Mock WFM Server..." + @./bin/server > /tmp/wfm-server.log 2>&1 & \ + echo $$! > /tmp/wfm-server.pid; \ + sleep 1; \ + echo "✅ Server started (PID: $$(cat /tmp/wfm-server.pid))" + +run-tests: build-tests + @echo "🧪 Running conformance tests..." + @./bin/run_tests + +FILE ?= device-scenarios/test-scenarios.json +run-custom-tests: build-tests + @echo "🧪 Running vendor scenarios from: $(FILE)" + @./bin/run_tests -file $(FILE) + +demo: build + @echo "" + @echo "╔════════════════════════════════════════════════════════════════════════════════╗" + @echo "║ DEMO: Device Supplier Conformance Suite ║" + @echo "║ ║" + @echo "║ This demonstrates a data-driven conformance testing framework for Margo ║" + @echo "║ No code changes needed to add test cases - just edit JSON files! ║" + @echo "╚════════════════════════════════════════════════════════════════════════════════╝" + @echo "" + @echo "📋 Step 1: Starting mock WFM server in background..." + @make run-server + @echo "📋 Step 2: Running conformance tests..." + @make run-tests + @echo "" + @echo "✅ Demo complete! Check reports/ folder for HTML report" + @echo "📌 Server is still running. Use 'make kill-server' to stop it" + @echo "" + +kill-server: + @echo "⛔ Stopping server..." + @if [ -f /tmp/wfm-server.pid ]; then \ + PID=$$(cat /tmp/wfm-server.pid); \ + if kill -0 $$PID 2>/dev/null; then \ + kill -15 $$PID; \ + sleep 1; \ + echo "✅ Server stopped (PID $$PID)"; \ + else \ + echo "⚠ Server process not running"; \ + fi; \ + rm -f /tmp/wfm-server.pid; \ + else \ + echo "⚠ No server process to stop"; \ + fi + +clean: + @echo "🧹 Cleaning up..." + @rm -rf bin/ + @rm -f /tmp/wfm-server.pid /tmp/wfm-server.log + @# Preserve go.sum and go.mod to avoid rebuild issues + @echo "✅ Clean complete" + +dev-setup: + @echo "📋 Developer Setup" + @echo "Installing Go dependencies..." + @go mod tidy + @echo "✅ Ready for development" diff --git a/device-supplier/README.md b/device-supplier/README.md new file mode 100644 index 0000000..1b1a681 --- /dev/null +++ b/device-supplier/README.md @@ -0,0 +1,128 @@ +# Margo Device Supplier Conformance Suite + +High-level entry point for running the suite and finding detailed documentation. + +## Current Status + +- RFC 9421 request signing and verification enabled +- Data-driven test and validation model (assertions.json controls all rules) +- Custom test-scenario JSON format for vendor-provided test cases + +## What Goes Where + +- Use this README for quick setup and daily commands. +- Use [Final-Summary.md](Final-Summary.md) for the complete vendor guide: test scenario format, Data-Generator CLI, Runner CLI, real device-agent setup, API reference, and troubleshooting. + +## Quick Start + +From this directory (`conformance/device-supplier`): + +1. Build binaries: + +```bash +make build +``` + +2. Start server (Terminal 1): + +```bash +make run-server +``` + +3. Run tests (Terminal 2): + +```bash +make run-tests +``` + +4. Open report: + +```bash +open reports/conformance-report-*.html +``` + +Expected summary: `Test Results: 43 PASSED, 0 FAILED`. + +## Frequently Used Commands + +| Command | Purpose | +|---|---| +| `make build` | Build server and test runner | +| `make run-server` | Start mock WFM server | +| `make run-tests` | Execute all conformance tests | +| `make demo` | Demo flow (starts server, runs tests) | +| `make kill-server` | Stop running server process | +| `make clean` | Remove build artifacts | + +## Detailed Documentation + +Full vendor guide: [Final-Summary.md](Final-Summary.md) + +- Architecture and two testing modes: [Final-Summary.md](Final-Summary.md#architecture) +- Custom test-scenario format: [Final-Summary.md](Final-Summary.md#part-1--create-your-test-scenarios) +- Data-Generator CLI usage: [Final-Summary.md](Final-Summary.md#part-2--register-scenarios-with-data-generator) +- Runner CLI usage: [Final-Summary.md](Final-Summary.md#part-3--run-conformance-tests) +- Real device-agent setup: [Final-Summary.md](Final-Summary.md#part-4--test-with-your-real-device-agent) +- API endpoint reference: [Final-Summary.md](Final-Summary.md#api-reference--all-8-endpoints) +- Validation rules (assertions.json): [Final-Summary.md](Final-Summary.md#validation-rules-reference-assertionsjson) +- Environment variables: [Final-Summary.md](Final-Summary.md#environment-variables) +- Troubleshooting: [Final-Summary.md](Final-Summary.md#troubleshooting) + +Additional certificate docs: + +- [docs/CERTIFICATE_ARCHITECTURE.md](docs/CERTIFICATE_ARCHITECTURE.md) +- [docs/CERTIFICATE_GENERATION.md](docs/CERTIFICATE_GENERATION.md) + +## Certificate Distribution for Real Device-Agent + +For this server/suite, the only required handoff to a real device-agent is the CA certificate. + +Copy `certs/ca-cert.pem` from this repo to the device-agent VM so the agent trusts the mock server CA. + +Example real device-agent path: + +```bash +cd ~/sandbox/poc/device/agent/config/ +ls -lrt +``` + +Copy command example (from suite host to agent host): + +```bash +scp certs/ca-cert.pem margo@margo-device-k3s:~/sandbox/poc/device/agent/config/ca-cert.pem +``` + +Or if you are on the same host: + +```bash +cp certs/ca-cert.pem ~/sandbox/poc/device/agent/config/ca-cert.pem +``` + +Current example path (from current real device-agent setup): + +```text +~/sandbox/poc/device/agent/config/ +``` + +Important: + +- This path is an example for the current environment. +- Vendor-provided device-agents may use a different cert/config location. +- The requirement remains the same: place `ca-cert.pem` in whatever location the device-agent is configured to read as its trusted CA. + +## Minimal Troubleshooting + +1. Server not reachable: + +```bash +make run-server +``` + +2. Signature failures (401): + +- Verify device cert/key pairing used by runner. +- See [Final-Summary.md](Final-Summary.md#certificate-handling). + +3. Validation failures (400/422): + +- Check request body against assertion rules in [Final-Summary.md](Final-Summary.md#assertion-schema). diff --git a/device-supplier/bin/run_tests b/device-supplier/bin/run_tests new file mode 100755 index 0000000000000000000000000000000000000000..4a121992bf10f9965c811960a1e932d7685024a6 GIT binary patch literal 9631523 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ℜ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

GS~l)3{;Dz4>Oxgd2B9k6 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

!kzTYrwd=7B0_ubCmd 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

3y{$0sM+5%OvA&-=4C#ip+Rljav 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
f$`b328Tnf2z zFu6}PN|kxDr{$2U_)x>e_E#D%7JhG}T51_^wKd!rvh$fqiL)v&9YP)AkMW5M3+h-N zXr0L4y`pb7ByebRDB(2H9)+Ih656#+uAQvIR`-c35(I2!aXY%bIjG^8{|gv>lIq}> zKdJ97TO!UXZ9cSj-~H-H*LSC0nnSPBt@b?VyPUQ)Cic~OYhW}_*09mjI1s~bIv=fI zbbZxpv|E;IKk$}tOZ@!ne*+ia#``wa!u_jyi4!-l+htIp=YDF z>Hk9l`znY}$4p^WLjFN-3TIb3i_7c$9@-yQ^A+JTi)ww%qFVbjyE0>h#)mdHKKv2O z!yg~E)9G$}*rM)d!KU2IgIhC61A_$|SuN0Wf=O}vV%B6$h&5j`)u;}`I-)46L4}t!Gp1bfQ<+H42Z1#RrA0fLSa55T z_jU@t$sI*BVsBEJ#EGm|L_WiraW{ zD|h5ia|252s6e?VOEU(l}eE? zf$yUpaQHPay<7UKu6T@9*Q4>RI@>E{?BMJnV~3S4Gl~Ai@w){F(ZmrpdWvlWG&$ zjDHvH=X8NcmN=^*&b-_A{n?FR+s%F4h{V}M6Ce>#M6>(8h?GO2q!iyuJ_e~f4CP!j_#w;do1VBtEB11gW+0 zO{r6ph3%+p_IDQB+!_&4yjQ!ql0=tLu zs(-YES6{m2N1VxY%M=>q3WdJIa`rg_wJ!9-E+Dg+vG|w!Th09*?AJOdw&`O+NJvy; z4jx(dG40{{lvm!?wTPUR@_y0DO32L_N1&tsRXy~tAh_}*YGe1L5s5xM3-eb9#pV?C zyYVv4rtC-P%6_2*iewq;U0cAGPIhbG8O~dD5LEP11Kn;g7yrI-4|_f1ZRjPpmABe| zP4sL%KNs=do2@^02oUm2jaJ)EPSKp!UVYh&*0b<<_Kz0xgI?aF?V9`V+8EX zPgi-{`db}klMl&T)Sx=1QHNJ&@YE@>?Ut>VzFnH$%f2bl-{|26K6C+5>BOC&wgg|tp*X}-g@Dx6()kjleh`4S;SRVl%vXm>F0Vl(CyCyGh`~qt`0Iyx)yu zO?}t0*YFQ2gmS8t_%}%kP)P{5o?-6W3sje&k|VR0{qeAd69)vNN?l_hLqA+<^x3*p z9QoGA^UevgLGB!sUNF~$k@SJBaeC1goX*dF*r$3Q2wD2lLaC23ESsZ1H2>M|=09)J zG)JUmZS46)AMWG3c}8CKrWkrA6j9KW&(PE1+CTk)=+ClW+HOiVRihzli_+CXpxL|l z!@qYwSz`1uw`OU za=!4^?J4$_w+p&V_ny(uWMSEAI@h);`Q*??gWAUBwGOo1#-lf; zeheCIbNZ2|>pvuv*Neoi50`aEVUG^0 zAQCU&Jdh5*QpOa0cZm15EBgGdwb)N&Bb>E7=3|YuBy1HbChSMAvz_v0w9mUp?AB6F z7!Kmi0Vbq=Zm+t0Mzp1lL10$vg+cy*UKU38UtzRM;ZtUX$(NlPS z@l{i2GJw>z&ncL3d2|2;_L$l_oEKMLe$`agpE*Weuda>`)vH<25EC}0W9`cf+0JJ= z>BMbYV6WuJ%eqJ98N+zfqMAA-M(*G`l9)o5 z7q5R?EL!s-7jFQk1jM$G7|n#rea@)Y#bRAS$GY@big&o;bL|2=fOu>6{JSmF*5N-S zsap83+K#R94>gxo{dD$q4Q%DX6!VdX(vLg-h}~E|AT;-Dlxj?zT1Mk%v|M_X$#-b( zB%T@#E}0dYD?mn~(A=@yg2-@($cSu2CV+^)e!{Zx+<(AV0T%4Foh&D5$2uNr{AJZ9 zbo&!l;_N1+pJ2J=Zu@ym`-zv(2hme(W#@~$E7MU8oEXqvJ?-)M01quFTi z%dPnZzuHfagoPD*9WGR@Cl}h`0v_|b?G)~NEh_7J< zvoU;_g_~*JmMIqp1`#s*4k=$#{jI6I?=ZKL`lB}??Q;wyXm_j6$Jdk(&=OxmS$p-Y z8CP74{2nx|{hETAmq&-SU4!%vcAiSHai%|9*Y^hAN5LE|mGeUxS*w8A5L;0(DZWFS zpCb+3E7Y_(ji~!dnmScYRlbS%dv)<=>f(Q>i~p%HzS<{(mSJ`%J0I>Hh$VY_j>ccI zAB2)S;3^F*jMt0(6&{w@$o3jOq<-Gi@TmHESA@g-I#hFi;nA2lL5XYI=<*=`S@Y5$ z{#osWn{ zbU&ZEA2Ad`@uL&Oa<}yp-jZ1jPhEM<^ck~Sue!Lgdf(`U)7q~sy7JQ2y(nconLald z&IsQ2jzy-V%<|P2Sg94x|AKBRY9$W!aTDIuSbOV!jP8P6KZilV^?SFU zaOKpiX8Cg(C1$oQu>K&b)2@=me_HPEX7C2h>Sq`{>k|^W1`~3dAXtMK&-z6N7%QjG zN1vRHn16vy7mKvG>V0>y<{ztC5nWsND!uei8g0f-(}j%$@m+E{#kYA$lJuiX&T^(4 zGm!a9@lVogstoZyR6!qyNbp7}gfXmPhWQDmq`WR0sLQgn^eH^M$?xYYrLeHC^1l{R z7e>SFCmDy1X!|A{I@B7x8(=ps^pJ4ahJH$=d)GmVSVDWMB^(*dc1{>DHxqwDUSyB z8=pKAJa!r$OUlPrEoogH^z~==a}kl=uFZRflAE#4gLY>(xoPbuHktHW&?hxWF@1ehXBW)+z$kRW7EFxxEAZqsz5$s-hSu(oYMB8bm?;y6$&8v-pbf z9q)7S9V8t1qz%T&n#k{v3cU`RS|8t_?KIo#$&(v@!KUx2BbCt+*ivRvR&6RD+gTVL zR_8NdNu4;bGg?$tGPl}V_3U#O@x^}8L8 z1`XX^^h+=%$}LlC1A+e3PO9D>O1?`SK7}?>TR{ze9oDe8b>=k}Uv}~3S2b22>cU_l5F_62i(D<|ts2EC zajPd)uZf-@wx|I19?>tV{b~8D?S} z^Y~Tis`AYGK4IlIZGu{oL2@9i)aJ{sMfx|7c8H24^jtsME5_1!@G&P4zo&Iq`#*_7|XoGQNZ6Yt$^8A|0@Dm+l5~rTU{owq|nZA0V z68tS$ys@3Bb6qQ7m|xZ=DhZ3dG<>&Q%_2jV)^f8#9YcQG>orSuoK`n*1?PECOLpcq z6rGM&NzbO8Wm6Ap+F5aH5h$+1B~gC1@YoKAB}WiyV=o$t6Y(!zb4MAaPR-9o5bftX zK7#zb$eckz@P((c5nRU=3dow8*hi^HiJ;63?;VJLk+pmmH&Wg4m2|s@Si1+&?%7%G zHvQ9Y`^rVxpm9!Hq5a%{s#~@ucOm_~6Mrn@e(iM36Tis#L^=DFgF!)Ok(?Xwiks4z$^+5(T|pLUA&Su{59;uMAc1AsyC)CizL+ygMNWqOSjRcEiVUe6V+?y=Ce4 zk?>O+Pn&iqw$;emw{T59vSwk^U5~$pB`T*jcU7t&^Qg;0SpOYK*5NLhT&sbDg z{IK+a4=j#b_^J0!o5tInK0tx#Nn|}0CKTRIR~P}nB1h{&mZK3_rz-t5l6qE5X7pe5 z_NUTl5&YKcCcm9sa=c7Uw&u{j4DxH7Uq5B@CF=?Wuej?z$@RBocc{u0cX15N_Oo^L zlgjSX4@|XR4rC7WwU##VMaZ(cEmZsRb@?TSy4d>+vSrAFEB^7D<*4_D?G(SH$}#;| zMr*!y1fT}ot+;|KI@YyUwsu4bJ*pN51gOMK!yGmJBgFn#09K_}0DDTlg3eUjK2N7< z-^%y4F`l7K#OIhj)8?GUebOe?c>p;2=#JwIeX>boya02-3-3jie0XHdQvq|;m;#kWMicS;wF6zT90iQq(%Li3ICLX;QG4?7R-ERDf z;BAZVyf{z?HS=6&0l=3;9*S)HEHWx**2%XBKePMifm;UayN&u+v#7!xWQU-j}j)NcGIdq5aQPh^u*T3Qq~Q-c1=^$lW~VAWmuc zX3|v9mX5sWiA@y^cO9exxR+mS>4=8&Qdg=3Z_cuGM8j#MH(%G-@YU2=$p4Of2KZBY zaqZMAZ;Dj(Z8(y1b8-h6;$Ba=^6DFS9X$+7SU%eDK@MxDgTZJ}%5TTHA7^Mes8c&Q z^RPU^1r(>Cp!UNOjs|mr>CgPExV4mHqp_-%rE56HwT|CoYMNQmppdMjv#Oj@!hYt~ zXm6>zl5na0QIMP(E*37)h>V~JH-xCA0gY&_clVb$Lu>v=tbX|_ZJ5C=2T6CB-XGGS zPlrntdC~EK-y#M+`ki<94|Hh+BYLOT{{20u%9S%1O5Ow0x*tHYaSTqr+|A)J=11*6 z&2XD9y)&CHa*vR7FE{1Yt+jL=R6WmH-A3&Fe7DTNP^V>!=2a~>v|mtc>3Xz6P_K=> zcpCdyunIx1%!_hu>nsDJW$<-Z-WWYjj?$`4_o5KZa?~pan1uN&i6o51 zOY<_J$xW4h))a@DU7-LP@(2AQFM3dOx%eyGW*2?(2IE7^uKegxHH!kitF0&wxBY@) zs{*MJ4DMEd+hgx=+kFxWmRHPZd2i>{#O6jAGTb)VFXzvB&Q=&LaJ4d6olhDS9uip? zR2ZqqZz$#dj=TLzqSM_s$L;yin;h`y1ntjkN01(LryOBi197$Bq{N3GoEJC%szYSK zS`0KC0PkUwTm;r@-vLlxoC6@TRr{RW0?Jv4LahT*hkE@sb7xhe;QbD{#u5KD-G25u z+HSM%^wlL$u+`&{O+bWPI$yG%GVnos&|IM&47Y93SKj65n|4gzv==o@$=pB6)-E~= zA(r8$cKgt3OLyGzHCS*~5A}^X;xxAsZo3yi}!+csxrQydF#54^74wT_Ty9UzS zq2S3oq2QY7Q1JQ6`~mi^;KEu3kz=}X`_a%8r^?yyi>3r;n`K4Y@%TUVen(7!GLL_p z{e6M`nUPBZJ77lY8ZveO=l@k#qF}-ylBV?483xx55=iL;>{8n)c7F2?Y`(ug__|4k z0HR}eBInwb9l={+?M9nBveN3tBs3_rzHnm@`LT=3$8FGQP6`HHn!S;~JL$ip{BPEO zHUh(K2m0?^|6$wxuK*+GrijfaiMT6hNi{)ctD3jRPPpX$aNAwHz)<*uqT`uNmqxGE zfXt^DqqyO$x_Dm{oQBhC2oPQquPH=l0l!7)mg@2;!p-Vp`kw@l^995&FAIdLE)_Ca zf=odUv)ht99q{C?C3jM47`Ti$ffeE$z zyx;Ne_9|`z+LipRBf|n-CdG*0bo_#^u8KC2^JlyiZKmxLpPww-17*ew#9k;vEk$Ih ziS4xMYC~!uZ;s=Qj6LcO9zP*whIA2V$c(l@!hM0TMu^X~)NP1pW;v@Swu~LE)b(j5 z-(3PfY-YNemSrg2?u=|r2kO1+QB6Q+W!2qC-NN50BF{Wk74eXm(k5P~1p$>h7Lyc8iwoXbu8P;g zZ4cxry9pePclh%xoGTDFjrxG#Y(#$!x1P>ZH9NWORn0pb>&woA*>KK5>fTl1w&Qu$ zR_9r4nfK9zB>XVz+!g%RSU9eRYvj4%c~DLK62`=sLhsR~elcLx3zlCp6|!|ND?#nH zovwa4G(?=uCT559%1^Ycl(L>0jZtT^W(l5gliLLbkr=_m`5lXB2!g+h*e^6ydSez zCFjJi$;q#aU7deUY-~<`@@dv*6rVxyKVAEDouLP612qAA>VCQp3H6MWHk)c;1`P1r*N zc32S3kY(@ml?2G9??l|ZviNs$79gL#C-JHq`cBoR&KIEXpIV{sf)g_I&C9B)Gku%? z<>-6tz1`FIrw2mQE$q8M#b@{(P~qGB?grBpmO#))`J17-k4%#nRrPf98Yhzv@=XIkJ@`z zH~u$UvDl?U_W4e6OxK2)=1y{ZucTnpz>>N=vUX!+iFah=*}&Kp$$ehNuI0AQo$0S1 z{j;1PV)B(ky91lwm0gvUHgi;~UjuVEHDERQgE3RlFF!a3p0X2xK^C0oSRzwGIXl*3 zG;BDb6V6V6XAX}>$Y^ub{Lb&xswS!g{@)A$vE4;5xbFc<07wk1&9lzOfImaOFs$J2t zvWIf>|2J4=wEVq9{p;lPSTfnGh3Y(=y>@L2%w=Ryo7U(-+)Oh?HDcVaVosMhxuyt z+i+eE#~c$y@oHkWRjg^)PupXa;!ho6(~$!Js(kW3YxtaC>2}yif&>()l{Cr86AZ#N zTL1o261k7}Ad!h#LAl7dtSBWkUbb&U5vVWp8r^rTJJm>rMp_R(F~4 zX8xFiqbP`c$DN2KN!is{lQQ?9rE~l-NKnO%UgHOh9bLaUhHv7jc|HZ^TH5N&EXc

f1HE)}rZ(iS3nJm-lEG*z)dwwGz8Rf4(7Z94AcO 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