From 440e66e36698216d786b9f74d8487292b41d05df Mon Sep 17 00:00:00 2001 From: konojunya Date: Fri, 4 Sep 2026 22:22:02 +0900 Subject: [PATCH 1/2] Expand audited provider icon catalogs --- .github/workflows/ci.yaml | 11 + Cargo.lock | 13 +- Cargo.toml | 7 +- README.md | 6 +- catalogs/aws.json | 2496 ++++++++++++ catalogs/azure.json | 5166 ++++++++++++++++++++++++ catalogs/gcp.json | 454 +++ catalogs/simple-icons.json | 674 ++++ docs/provider-icon-import.md | 56 +- scripts/generate-provider-catalogs.mjs | 507 +++ scripts/validate-provider-catalogs.mjs | 117 + src/lib.rs | 186 +- src/provider.rs | 1177 +++--- src/provider_catalog.rs | 148 + tests/cli.rs | 35 +- 15 files changed, 10529 insertions(+), 524 deletions(-) create mode 100644 catalogs/aws.json create mode 100644 catalogs/azure.json create mode 100644 catalogs/gcp.json create mode 100644 catalogs/simple-icons.json create mode 100644 scripts/generate-provider-catalogs.mjs create mode 100644 scripts/validate-provider-catalogs.mjs create mode 100644 src/provider_catalog.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 914e5a8..1db577e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -30,6 +30,8 @@ jobs: path: .stack-specification - name: Check whitespace run: git diff --check "$(git hash-object -t tree /dev/null)" HEAD + - name: Validate provider catalogs + run: node scripts/validate-provider-catalogs.mjs - name: Install latest stable Rust toolchain run: rustup toolchain install stable --profile minimal --component clippy,rustfmt,llvm-tools-preview - name: Check formatting @@ -67,6 +69,8 @@ jobs: ./target/release/stack fmt --help ./target/release/stack render --help ./target/release/stack icons --help + ./target/release/stack icons list + ./target/release/stack icons list aws s3 ./target/release/stack icons import --help - name: Verify repository files run: | @@ -83,6 +87,13 @@ jobs: test -s Cargo.lock test -s src/main.rs test -s src/provider.rs + test -s src/provider_catalog.rs + test -s catalogs/aws.json + test -s catalogs/gcp.json + test -s catalogs/azure.json + test -s catalogs/simple-icons.json + test -s scripts/generate-provider-catalogs.mjs + test -s scripts/validate-provider-catalogs.mjs test -s tests/specification-revision test -s tests/fixtures/render.stack diff --git a/Cargo.lock b/Cargo.lock index 7caad08..41491e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -222,9 +222,10 @@ dependencies = [ [[package]] name = "stack-cli" -version = "0.1.0" +version = "0.2.0" dependencies = [ "roxmltree", + "serde", "serde_json", "sha2", "stack-engine", @@ -239,8 +240,8 @@ source = "git+https://github.com/stack-sh/compiler.git?rev=4a18fac42afc2256a1bb3 [[package]] name = "stack-engine" -version = "0.5.0" -source = "git+https://github.com/stack-sh/engine.git?rev=c82595e33c6f26b67fec7b5c2171921765e30000#c82595e33c6f26b67fec7b5c2171921765e30000" +version = "0.6.0" +source = "git+https://github.com/stack-sh/engine.git?rev=b4a85b09f0d75d5966d50dc76b39d7ea4989c823#b4a85b09f0d75d5966d50dc76b39d7ea4989c823" dependencies = [ "roxmltree", "serde_json", @@ -253,15 +254,15 @@ dependencies = [ [[package]] name = "stack-formatter" version = "0.1.0" -source = "git+https://github.com/stack-sh/engine.git?rev=c82595e33c6f26b67fec7b5c2171921765e30000#c82595e33c6f26b67fec7b5c2171921765e30000" +source = "git+https://github.com/stack-sh/engine.git?rev=b4a85b09f0d75d5966d50dc76b39d7ea4989c823#b4a85b09f0d75d5966d50dc76b39d7ea4989c823" dependencies = [ "stack-compiler", ] [[package]] name = "stack-theme" -version = "0.4.0" -source = "git+https://github.com/stack-sh/theme.git?rev=2347315e6e86ab9d2708e05fd3f9b5f3d87e1241#2347315e6e86ab9d2708e05fd3f9b5f3d87e1241" +version = "0.5.0" +source = "git+https://github.com/stack-sh/theme.git?rev=13e41b84167e810c36c3ab87fff2e1fda84a2b8f#13e41b84167e810c36c3ab87fff2e1fda84a2b8f" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index f9e979b..a29857d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stack-cli" -version = "0.1.0" +version = "0.2.0" edition = "2024" rust-version = "1.85" publish = false @@ -15,10 +15,11 @@ path = "src/main.rs" [dependencies] roxmltree = "=0.21.1" +serde = { version = "=1.0.229", features = ["derive"] } serde_json = "=1.0.151" sha2 = "=0.11.0" -stack-engine = { git = "https://github.com/stack-sh/engine.git", rev = "c82595e33c6f26b67fec7b5c2171921765e30000" } -stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "2347315e6e86ab9d2708e05fd3f9b5f3d87e1241" } +stack-engine = { git = "https://github.com/stack-sh/engine.git", rev = "b4a85b09f0d75d5966d50dc76b39d7ea4989c823" } +stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "13e41b84167e810c36c3ab87fff2e1fda84a2b8f" } zip = { version = "=6.0.0", default-features = false, features = ["deflate-flate2-zlib-rs"] } [features] diff --git a/README.md b/README.md index ff87624..cffcfea 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ stack fmt --check arch.stack stack fmt - stack render arch.stack stack render arch.stack -o arch.svg +stack icons list +stack icons list aws s3 stack icons import aws ~/Downloads/aws-icons.zip --accept-terms -o .stack-icons/aws stack render arch.stack --provider-pack .stack-icons/aws -o arch.svg --notice arch.NOTICE.md ``` @@ -23,7 +25,9 @@ stack render arch.stack --provider-pack .stack-icons/aws -o arch.svg --notice ar `stack render` uses the same engine pipeline to produce deterministic standalone SVG. Without `-o`, standard output contains only SVG. With `-o`, the output is written atomically in the destination directory. Repeat `--provider-pack ` to load local imported packs, and use `--notice ` to save the exact provider pack revisions, terms, source archives, and icon IDs embedded in that artifact. Pack files are bounded and validated before rendering; the command performs no download or upload. Diagnostics remain on standard error, warnings preserve SVG, and Stack errors never create or replace output. -`stack icons import` creates a local provider pack from an official ZIP archive that the user selected. It performs no network request or upload, requires explicit terms acceptance, verifies the complete archive against an audited SHA-256, reads only allowlisted SVG entries with fixed size limits, removes active or external content, preserves the official colors and geometry, and writes the manifest, notice, and processed SVGs atomically to a new directory. The initial audited profiles import 7 AWS, 6 Google Cloud, or 5 Azure icons. See [the provider icon import guide](./docs/provider-icon-import.md) for exact sources, hashes, IDs, and terms. +`stack icons list [PROVIDER] [QUERY]` searches the asset-free catalog by ID, product name, or category. The catalog currently contains 1,051 IDs: 305 AWS, 45 Google Cloud, 639 Azure, and 62 curated developer and collaboration tool icons. This command reads only metadata embedded in the CLI. + +`stack icons import` creates a local provider pack from official ZIP archives that the user selected. It performs no network request or upload, requires explicit terms acceptance, verifies every complete archive against an audited SHA-256, reads only allowlisted SVG entries with fixed size limits, removes active or external content, preserves official colors and geometry, and writes the manifest, notice, and processed SVGs atomically to a new directory. Google Cloud combines its core and category archives with `--source categories=`. Simple Icons entries also retain the recorded rights-owner source and brand-guideline links because that project's CC0 distribution does not grant rights to every underlying brand. See [the provider icon import guide](./docs/provider-icon-import.md) for sources, hashes, usage, and rights boundaries. | Result | Exit status | | --- | ---: | diff --git a/catalogs/aws.json b/catalogs/aws.json new file mode 100644 index 0000000..996cbcc --- /dev/null +++ b/catalogs/aws.json @@ -0,0 +1,2496 @@ +{ + "catalogVersion": "1.0", + "packVersion": "0.2.0", + "provider": { + "id": "aws", + "name": "Amazon Web Services" + }, + "source": { + "pageUrl": "https://aws.amazon.com/architecture/icons/", + "archiveUrl": "https://d1.awsstatic.com/onedam/marketing-channels/website/public/shared/architecture-icon-release/Icon-package_07312026.5846e92413caa21490223536cc97f1269e44fa92.zip", + "archiveSha256": "sha256:d2d166c453526471749d520e0db022c459abef759d2946cf2dd1d1c992dc6526", + "release": "Icon-package_07312026", + "retrievedAt": "2026-09-04", + "termsUrl": "https://aws.amazon.com/trademark-guidelines/", + "termsReviewedAt": "2026-09-04", + "reviewAfter": "2026-12-03", + "copyright": "Copyright Amazon Web Services, Inc. or its affiliates", + "licenseId": "LicenseRef-AWS-Architecture-Icons-Terms", + "archiveLicenseIncluded": false + }, + "additionalSources": [], + "rights": { + "termsAcceptanceRequired": true, + "permittedOutputs": [ + "architecture-diagram", + "whitepaper", + "presentation", + "data-sheet", + "poster" + ], + "redistribution": { + "cargo": false, + "npm": false, + "wasm": false, + "webAsset": false, + "nativeBinary": false, + "generatedOutput": true + }, + "processing": { + "localOnly": true, + "automaticDownload": false, + "serverUpload": false, + "preserveColors": true, + "preserveGeometry": true, + "productNameNearby": true + }, + "modificationPolicy": "visual-preservation-only" + }, + "notice": { + "attribution": "AWS architecture icons are owned by Amazon Web Services, Inc. or its affiliates.", + "termsSummary": "Use is limited to the architecture-diagram materials described by the official AWS Architecture Icons page and applicable AWS trademark guidelines.", + "nonEndorsement": "Amazon Web Services does not sponsor or endorse this diagram or Stack." + }, + "icons": [ + { + "id": "aws:amazon-api-gateway", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon API Gateway", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-API-Gateway_48.svg" + }, + { + "id": "aws:amazon-appflow", + "subject": "Application Integration product or service", + "productName": "Amazon AppFlow", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-AppFlow_48.svg" + }, + { + "id": "aws:amazon-application-recovery-controller", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon Application Recovery Controller", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-Application-Recovery-Controller_48.svg" + }, + { + "id": "aws:amazon-athena", + "subject": "Analytics product or service", + "productName": "Amazon Athena", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Athena_48.svg" + }, + { + "id": "aws:amazon-augmented-ai-a2i", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Augmented AI A2I", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Augmented-AI-A2I_48.svg" + }, + { + "id": "aws:amazon-aurora", + "subject": "Databases product or service", + "productName": "Amazon Aurora", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-Aurora_48.svg" + }, + { + "id": "aws:amazon-bedrock", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Bedrock", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Bedrock_48.svg" + }, + { + "id": "aws:amazon-bedrock-agentcore", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Bedrock AgentCore", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Bedrock-AgentCore_48.svg" + }, + { + "id": "aws:amazon-braket", + "subject": "Quantum Technologies product or service", + "productName": "Amazon Braket", + "recommendedNodeKind": "service", + "category": "Quantum Technologies", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Quantum-Technologies/48/Arch_Amazon-Braket_48.svg" + }, + { + "id": "aws:amazon-chime", + "subject": "Business Applications product or service", + "productName": "Amazon Chime", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Chime_48.svg" + }, + { + "id": "aws:amazon-chime-sdk", + "subject": "Business Applications product or service", + "productName": "Amazon Chime SDK", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Chime-SDK_48.svg" + }, + { + "id": "aws:amazon-cloud-directory", + "subject": "Security Identity product or service", + "productName": "Amazon Cloud Directory", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Cloud-Directory_48.svg" + }, + { + "id": "aws:amazon-cloudfront", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon CloudFront", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-CloudFront_48.svg" + }, + { + "id": "aws:amazon-cloudsearch", + "subject": "Analytics product or service", + "productName": "Amazon CloudSearch", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-CloudSearch_48.svg" + }, + { + "id": "aws:amazon-cloudwatch", + "subject": "Management Tools product or service", + "productName": "Amazon CloudWatch", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_Amazon-CloudWatch_48.svg" + }, + { + "id": "aws:amazon-codecatalyst", + "subject": "Developer Tools product or service", + "productName": "Amazon CodeCatalyst", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_Amazon-CodeCatalyst_48.svg" + }, + { + "id": "aws:amazon-codeguru", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon CodeGuru", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-CodeGuru_48.svg" + }, + { + "id": "aws:amazon-codewhisperer", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon CodeWhisperer", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-CodeWhisperer_48.svg" + }, + { + "id": "aws:amazon-cognito", + "subject": "Security Identity product or service", + "productName": "Amazon Cognito", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Cognito_48.svg" + }, + { + "id": "aws:amazon-comprehend", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Comprehend", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Comprehend_48.svg" + }, + { + "id": "aws:amazon-comprehend-medical", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Comprehend Medical", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Comprehend-Medical_48.svg" + }, + { + "id": "aws:amazon-connect", + "subject": "Business Applications product or service", + "productName": "Amazon Connect", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Connect_48.svg" + }, + { + "id": "aws:amazon-corretto", + "subject": "Developer Tools product or service", + "productName": "Amazon Corretto", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_Amazon-Corretto_48.svg" + }, + { + "id": "aws:amazon-data-firehose", + "subject": "Analytics product or service", + "productName": "Amazon Data Firehose", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Data-Firehose_48.svg" + }, + { + "id": "aws:amazon-datazone", + "subject": "Analytics product or service", + "productName": "Amazon DataZone", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-DataZone_48.svg" + }, + { + "id": "aws:amazon-dcv", + "subject": "Compute product or service", + "productName": "Amazon DCV", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-DCV_48.svg" + }, + { + "id": "aws:amazon-detective", + "subject": "Security Identity product or service", + "productName": "Amazon Detective", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Detective_48.svg" + }, + { + "id": "aws:amazon-devops-guru", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon DevOps Guru", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-DevOps-Guru_48.svg" + }, + { + "id": "aws:amazon-documentdb", + "subject": "Databases product or service", + "productName": "Amazon DocumentDB", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-DocumentDB_48.svg" + }, + { + "id": "aws:amazon-ec2-auto-scaling", + "subject": "Compute product or service", + "productName": "Amazon EC2 Auto Scaling", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-EC2-Auto-Scaling_48.svg" + }, + { + "id": "aws:amazon-ec2-image-builder", + "subject": "Compute product or service", + "productName": "Amazon EC2 Image Builder", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-EC2-Image-Builder_48.svg" + }, + { + "id": "aws:amazon-ecs-anywhere", + "subject": "Containers product or service", + "productName": "Amazon ECS Anywhere", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-ECS-Anywhere_48.svg" + }, + { + "id": "aws:amazon-efs", + "subject": "Storage product or service", + "productName": "Amazon EFS", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-EFS_48.svg" + }, + { + "id": "aws:amazon-eks-anywhere", + "subject": "Containers product or service", + "productName": "Amazon EKS Anywhere", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-EKS-Anywhere_48.svg" + }, + { + "id": "aws:amazon-eks-distro", + "subject": "Containers product or service", + "productName": "Amazon EKS Distro", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-EKS-Distro_48.svg" + }, + { + "id": "aws:amazon-elastic-block-store", + "subject": "Storage product or service", + "productName": "Amazon Elastic Block Store", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-Elastic-Block-Store_48.svg" + }, + { + "id": "aws:amazon-elastic-container-registry", + "subject": "Containers product or service", + "productName": "Amazon Elastic Container Registry", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-Elastic-Container-Registry_48.svg" + }, + { + "id": "aws:amazon-elastic-container-service", + "subject": "Containers product or service", + "productName": "Amazon Elastic Container Service", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-Elastic-Container-Service_48.svg" + }, + { + "id": "aws:amazon-elastic-inference", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Elastic Inference", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Elastic-Inference_48.svg" + }, + { + "id": "aws:amazon-elastic-vmware-service", + "subject": "Compute product or service", + "productName": "Amazon Elastic VMware Service", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-Elastic-VMware-Service_48.svg" + }, + { + "id": "aws:amazon-elasticache", + "subject": "Databases product or service", + "productName": "Amazon ElastiCache", + "recommendedNodeKind": "cache", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-ElastiCache_48.svg" + }, + { + "id": "aws:amazon-emr", + "subject": "Analytics product or service", + "productName": "Amazon EMR", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-EMR_48.svg" + }, + { + "id": "aws:amazon-eventbridge", + "subject": "Application Integration product or service", + "productName": "Amazon EventBridge", + "recommendedNodeKind": "queue", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-EventBridge_48.svg" + }, + { + "id": "aws:amazon-file-cache", + "subject": "Storage product or service", + "productName": "Amazon File Cache", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-File-Cache_48.svg" + }, + { + "id": "aws:amazon-finspace", + "subject": "Analytics product or service", + "productName": "Amazon FinSpace", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-FinSpace_48.svg" + }, + { + "id": "aws:amazon-forecast", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Forecast", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Forecast_48.svg" + }, + { + "id": "aws:amazon-fraud-detector", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Fraud Detector", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Fraud-Detector_48.svg" + }, + { + "id": "aws:amazon-fsx", + "subject": "Storage product or service", + "productName": "Amazon FSx", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-FSx_48.svg" + }, + { + "id": "aws:amazon-fsx-for-lustre", + "subject": "Storage product or service", + "productName": "Amazon FSx for Lustre", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-FSx-for-Lustre_48.svg" + }, + { + "id": "aws:amazon-fsx-for-netapp-ontap", + "subject": "Storage product or service", + "productName": "Amazon FSx for NetApp ONTAP", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-FSx-for-NetApp-ONTAP_48.svg" + }, + { + "id": "aws:amazon-fsx-for-openzfs", + "subject": "Storage product or service", + "productName": "Amazon FSx for OpenZFS", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-FSx-for-OpenZFS_48.svg" + }, + { + "id": "aws:amazon-fsx-for-wfs", + "subject": "Storage product or service", + "productName": "Amazon FSx for WFS", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-FSx-for-WFS_48.svg" + }, + { + "id": "aws:amazon-gamelift-servers", + "subject": "Games product or service", + "productName": "Amazon GameLift Servers", + "recommendedNodeKind": "service", + "category": "Games", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Games/48/Arch_Amazon-GameLift-Servers_48.svg" + }, + { + "id": "aws:amazon-gamelift-streams", + "subject": "Games product or service", + "productName": "Amazon GameLift Streams", + "recommendedNodeKind": "service", + "category": "Games", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Games/48/Arch_Amazon-GameLift-Streams_48.svg" + }, + { + "id": "aws:amazon-guardduty", + "subject": "Security Identity product or service", + "productName": "Amazon GuardDuty", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-GuardDuty_48.svg" + }, + { + "id": "aws:amazon-inspector", + "subject": "Security Identity product or service", + "productName": "Amazon Inspector", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Inspector_48.svg" + }, + { + "id": "aws:amazon-interactive-video-service", + "subject": "Media Services product or service", + "productName": "Amazon Interactive Video Service", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_Amazon-Interactive-Video-Service_48.svg" + }, + { + "id": "aws:amazon-kendra", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Kendra", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Kendra_48.svg" + }, + { + "id": "aws:amazon-keyspaces", + "subject": "Databases product or service", + "productName": "Amazon Keyspaces", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-Keyspaces_48.svg" + }, + { + "id": "aws:amazon-kinesis", + "subject": "Analytics product or service", + "productName": "Amazon Kinesis", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Kinesis_48.svg" + }, + { + "id": "aws:amazon-kinesis-data-streams", + "subject": "Analytics product or service", + "productName": "Amazon Kinesis Data Streams", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Kinesis-Data-Streams_48.svg" + }, + { + "id": "aws:amazon-kinesis-video-streams", + "subject": "Analytics product or service", + "productName": "Amazon Kinesis Video Streams", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Kinesis-Video-Streams_48.svg" + }, + { + "id": "aws:amazon-kinesis-video-streams-media-services", + "subject": "Media Services product or service", + "productName": "Amazon Kinesis Video Streams", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_Amazon-Kinesis-Video-Streams_48.svg" + }, + { + "id": "aws:amazon-lex", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Lex", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Lex_48.svg" + }, + { + "id": "aws:amazon-lightsail", + "subject": "Compute product or service", + "productName": "Amazon Lightsail", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-Lightsail_48.svg" + }, + { + "id": "aws:amazon-lightsail-for-research", + "subject": "Compute product or service", + "productName": "Amazon Lightsail for Research", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-Lightsail-for-Research_48.svg" + }, + { + "id": "aws:amazon-location-service", + "subject": "Front End Web Mobile product or service", + "productName": "Amazon Location Service", + "recommendedNodeKind": "service", + "category": "Front End Web Mobile", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Front-End-Web-Mobile/48/Arch_Amazon-Location-Service_48.svg" + }, + { + "id": "aws:amazon-lookout-for-equipment", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Lookout for Equipment", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Lookout-for-Equipment_48.svg" + }, + { + "id": "aws:amazon-lookout-for-vision", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Lookout for Vision", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Lookout-for-Vision_48.svg" + }, + { + "id": "aws:amazon-macie", + "subject": "Security Identity product or service", + "productName": "Amazon Macie", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Macie_48.svg" + }, + { + "id": "aws:amazon-managed-blockchain", + "subject": "Blockchain product or service", + "productName": "Amazon Managed Blockchain", + "recommendedNodeKind": "service", + "category": "Blockchain", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Blockchain/48/Arch_Amazon-Managed-Blockchain_48.svg" + }, + { + "id": "aws:amazon-managed-grafana", + "subject": "Management Tools product or service", + "productName": "Amazon Managed Grafana", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_Amazon-Managed-Grafana_48.svg" + }, + { + "id": "aws:amazon-managed-service-for-apache-flink", + "subject": "Analytics product or service", + "productName": "Amazon Managed Service for Apache Flink", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Managed-Service-for-Apache-Flink_48.svg" + }, + { + "id": "aws:amazon-managed-service-for-prometheus", + "subject": "Management Tools product or service", + "productName": "Amazon Managed Service for Prometheus", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_Amazon-Managed-Service-for-Prometheus_48.svg" + }, + { + "id": "aws:amazon-managed-streaming-for-apache-kafka", + "subject": "Analytics product or service", + "productName": "Amazon Managed Streaming for Apache Kafka", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Managed-Streaming-for-Apache-Kafka_48.svg" + }, + { + "id": "aws:amazon-managed-workflows-for-apache-airflow", + "subject": "Application Integration product or service", + "productName": "Amazon Managed Workflows for Apache Airflow", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-Managed-Workflows-for-Apache-Airflow_48.svg" + }, + { + "id": "aws:amazon-memorydb", + "subject": "Databases product or service", + "productName": "Amazon MemoryDB", + "recommendedNodeKind": "cache", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-MemoryDB_48.svg" + }, + { + "id": "aws:amazon-monitron", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Monitron", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Monitron_48.svg" + }, + { + "id": "aws:amazon-mq", + "subject": "Application Integration product or service", + "productName": "Amazon MQ", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-MQ_48.svg" + }, + { + "id": "aws:amazon-neptune", + "subject": "Databases product or service", + "productName": "Amazon Neptune", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-Neptune_48.svg" + }, + { + "id": "aws:amazon-nova", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Nova", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Nova_48.svg" + }, + { + "id": "aws:amazon-opensearch-service", + "subject": "Analytics product or service", + "productName": "Amazon OpenSearch Service", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-OpenSearch-Service_48.svg" + }, + { + "id": "aws:amazon-personalize", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Personalize", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Personalize_48.svg" + }, + { + "id": "aws:amazon-pinpoint", + "subject": "Business Applications product or service", + "productName": "Amazon Pinpoint", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Pinpoint_48.svg" + }, + { + "id": "aws:amazon-pinpoint-apis", + "subject": "Business Applications product or service", + "productName": "Amazon Pinpoint APIs", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Pinpoint-APIs_48.svg" + }, + { + "id": "aws:amazon-polly", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Polly", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Polly_48.svg" + }, + { + "id": "aws:amazon-q", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Q", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Q_48.svg" + }, + { + "id": "aws:amazon-quick", + "subject": "Business Applications product or service", + "productName": "Amazon Quick", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Quick_48.svg" + }, + { + "id": "aws:amazon-redshift", + "subject": "Analytics product or service", + "productName": "Amazon Redshift", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-Redshift_48.svg" + }, + { + "id": "aws:amazon-rekognition", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Rekognition", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Rekognition_48.svg" + }, + { + "id": "aws:amazon-route-53", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon Route 53", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-Route-53_48.svg" + }, + { + "id": "aws:amazon-s3-on-outposts", + "subject": "Storage product or service", + "productName": "Amazon S3 on Outposts", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-S3-on-Outposts_48.svg" + }, + { + "id": "aws:amazon-sagemaker", + "subject": "Analytics product or service", + "productName": "Amazon SageMaker", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_Amazon-SageMaker_48.svg" + }, + { + "id": "aws:amazon-sagemaker-ai", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon SageMaker AI", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-SageMaker-AI_48.svg" + }, + { + "id": "aws:amazon-sagemaker-ground-truth", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon SageMaker Ground Truth", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-SageMaker-Ground-Truth_48.svg" + }, + { + "id": "aws:amazon-sagemaker-studio-lab", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon SageMaker Studio Lab", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-SageMaker-Studio-Lab_48.svg" + }, + { + "id": "aws:amazon-security-lake", + "subject": "Security Identity product or service", + "productName": "Amazon Security Lake", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Security-Lake_48.svg" + }, + { + "id": "aws:amazon-simple-email-service", + "subject": "Business Applications product or service", + "productName": "Amazon Simple Email Service", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-Simple-Email-Service_48.svg" + }, + { + "id": "aws:amazon-simple-notification-service", + "subject": "Application Integration product or service", + "productName": "Amazon Simple Notification Service", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-Simple-Notification-Service_48.svg" + }, + { + "id": "aws:amazon-simple-storage-service-glacier", + "subject": "Storage product or service", + "productName": "Amazon Simple Storage Service Glacier", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-Simple-Storage-Service-Glacier_48.svg" + }, + { + "id": "aws:amazon-textract", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Textract", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Textract_48.svg" + }, + { + "id": "aws:amazon-timestream", + "subject": "Databases product or service", + "productName": "Amazon Timestream", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-Timestream_48.svg" + }, + { + "id": "aws:amazon-transcribe", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Transcribe", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Transcribe_48.svg" + }, + { + "id": "aws:amazon-translate", + "subject": "Artificial Intelligence product or service", + "productName": "Amazon Translate", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Amazon-Translate_48.svg" + }, + { + "id": "aws:amazon-verified-permissions", + "subject": "Security Identity product or service", + "productName": "Amazon Verified Permissions", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_Amazon-Verified-Permissions_48.svg" + }, + { + "id": "aws:amazon-virtual-private-cloud", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon Virtual Private Cloud", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-Virtual-Private-Cloud_48.svg" + }, + { + "id": "aws:amazon-vpc-lattice", + "subject": "Networking Content Delivery product or service", + "productName": "Amazon VPC Lattice", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Amazon-VPC-Lattice_48.svg" + }, + { + "id": "aws:amazon-workdocs", + "subject": "Business Applications product or service", + "productName": "Amazon WorkDocs", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-WorkDocs_48.svg" + }, + { + "id": "aws:amazon-workdocs-sdk", + "subject": "Business Applications product or service", + "productName": "Amazon WorkDocs SDK", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-WorkDocs-SDK_48.svg" + }, + { + "id": "aws:amazon-workmail", + "subject": "Business Applications product or service", + "productName": "Amazon WorkMail", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_Amazon-WorkMail_48.svg" + }, + { + "id": "aws:amazon-workspaces", + "subject": "End User Computing product or service", + "productName": "Amazon WorkSpaces", + "recommendedNodeKind": "service", + "category": "End User Computing", + "archivePath": "Architecture-Service-Icons_07312026/Arch_End-User-Computing/48/Arch_Amazon-WorkSpaces_48.svg" + }, + { + "id": "aws:apache-mxnet-on-aws", + "subject": "Artificial Intelligence product or service", + "productName": "Apache MXNet on AWS", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_Apache-MXNet-on-AWS_48.svg" + }, + { + "id": "aws:aws-activate", + "subject": "Customer Enablement product or service", + "productName": "AWS Activate", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-Activate_48.svg" + }, + { + "id": "aws:aws-amplify", + "subject": "Front End Web Mobile product or service", + "productName": "AWS Amplify", + "recommendedNodeKind": "service", + "category": "Front End Web Mobile", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Front-End-Web-Mobile/48/Arch_AWS-Amplify_48.svg" + }, + { + "id": "aws:aws-app-mesh", + "subject": "Networking Content Delivery product or service", + "productName": "AWS App Mesh", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-App-Mesh_48.svg" + }, + { + "id": "aws:aws-app-runner", + "subject": "Compute product or service", + "productName": "AWS App Runner", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-App-Runner_48.svg" + }, + { + "id": "aws:aws-app-studio", + "subject": "Artificial Intelligence product or service", + "productName": "AWS App Studio", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-App-Studio_48.svg" + }, + { + "id": "aws:aws-appconfig", + "subject": "Management Tools product or service", + "productName": "AWS AppConfig", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-AppConfig_48.svg" + }, + { + "id": "aws:aws-appfabric", + "subject": "Business Applications product or service", + "productName": "AWS AppFabric", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_AWS-AppFabric_48.svg" + }, + { + "id": "aws:aws-application-auto-scaling", + "subject": "Management Tools product or service", + "productName": "AWS Application Auto Scaling", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Application-Auto-Scaling_48.svg" + }, + { + "id": "aws:aws-application-discovery-service", + "subject": "Migration Modernization product or service", + "productName": "AWS Application Discovery Service", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Application-Discovery-Service_48.svg" + }, + { + "id": "aws:aws-application-migration-service", + "subject": "Migration Modernization product or service", + "productName": "AWS Application Migration Service", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Application-Migration-Service_48.svg" + }, + { + "id": "aws:aws-appsync", + "subject": "Application Integration product or service", + "productName": "AWS AppSync", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_AWS-AppSync_48.svg" + }, + { + "id": "aws:aws-artifact", + "subject": "Security Identity product or service", + "productName": "AWS Artifact", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Artifact_48.svg" + }, + { + "id": "aws:aws-audit-manager", + "subject": "Security Identity product or service", + "productName": "AWS Audit Manager", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Audit-Manager_48.svg" + }, + { + "id": "aws:aws-auto-scaling", + "subject": "Management Tools product or service", + "productName": "AWS Auto Scaling", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Auto-Scaling_48.svg" + }, + { + "id": "aws:aws-b2b-data-interchange", + "subject": "Application Integration product or service", + "productName": "AWS B2B Data Interchange", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_AWS-B2B-Data-Interchange_48.svg" + }, + { + "id": "aws:aws-backint-agent", + "subject": "Management Tools product or service", + "productName": "AWS Backint Agent", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Backint-Agent_48.svg" + }, + { + "id": "aws:aws-backup", + "subject": "Storage product or service", + "productName": "AWS Backup", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_AWS-Backup_48.svg" + }, + { + "id": "aws:aws-batch", + "subject": "Compute product or service", + "productName": "AWS Batch", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Batch_48.svg" + }, + { + "id": "aws:aws-billing-conductor", + "subject": "Cloud Financial Management product or service", + "productName": "AWS Billing Conductor", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_AWS-Billing-Conductor_48.svg" + }, + { + "id": "aws:aws-budgets", + "subject": "Cloud Financial Management product or service", + "productName": "AWS Budgets", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_AWS-Budgets_48.svg" + }, + { + "id": "aws:aws-certificate-manager", + "subject": "Security Identity product or service", + "productName": "AWS Certificate Manager", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Certificate-Manager_48.svg" + }, + { + "id": "aws:aws-chatbot", + "subject": "Management Tools product or service", + "productName": "AWS Chatbot", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Chatbot_48.svg" + }, + { + "id": "aws:aws-clean-rooms", + "subject": "Analytics product or service", + "productName": "AWS Clean Rooms", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Clean-Rooms_48.svg" + }, + { + "id": "aws:aws-client-vpn", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Client VPN", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Client-VPN_48.svg" + }, + { + "id": "aws:aws-cloud-control-api", + "subject": "Developer Tools product or service", + "productName": "AWS Cloud Control API", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Cloud-Control-API_48.svg" + }, + { + "id": "aws:aws-cloud-development-kit", + "subject": "Developer Tools product or service", + "productName": "AWS Cloud Development Kit", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Cloud-Development-Kit_48.svg" + }, + { + "id": "aws:aws-cloud-map", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Cloud Map", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Cloud-Map_48.svg" + }, + { + "id": "aws:aws-cloud-wan", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Cloud WAN", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Cloud-WAN_48.svg" + }, + { + "id": "aws:aws-cloud9", + "subject": "Developer Tools product or service", + "productName": "AWS Cloud9", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Cloud9_48.svg" + }, + { + "id": "aws:aws-cloudformation", + "subject": "Management Tools product or service", + "productName": "AWS CloudFormation", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-CloudFormation_48.svg" + }, + { + "id": "aws:aws-cloudhsm", + "subject": "Security Identity product or service", + "productName": "AWS CloudHSM", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-CloudHSM_48.svg" + }, + { + "id": "aws:aws-cloudshell", + "subject": "Developer Tools product or service", + "productName": "AWS CloudShell", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CloudShell_48.svg" + }, + { + "id": "aws:aws-cloudtrail", + "subject": "Management Tools product or service", + "productName": "AWS CloudTrail", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-CloudTrail_48.svg" + }, + { + "id": "aws:aws-codeartifact", + "subject": "Developer Tools product or service", + "productName": "AWS CodeArtifact", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CodeArtifact_48.svg" + }, + { + "id": "aws:aws-codebuild", + "subject": "Developer Tools product or service", + "productName": "AWS CodeBuild", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CodeBuild_48.svg" + }, + { + "id": "aws:aws-codecommit", + "subject": "Developer Tools product or service", + "productName": "AWS CodeCommit", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CodeCommit_48.svg" + }, + { + "id": "aws:aws-codedeploy", + "subject": "Developer Tools product or service", + "productName": "AWS CodeDeploy", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CodeDeploy_48.svg" + }, + { + "id": "aws:aws-codepipeline", + "subject": "Developer Tools product or service", + "productName": "AWS CodePipeline", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-CodePipeline_48.svg" + }, + { + "id": "aws:aws-command-line-interface", + "subject": "Developer Tools product or service", + "productName": "AWS Command Line Interface", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Command-Line-Interface_48.svg" + }, + { + "id": "aws:aws-compute-optimizer", + "subject": "Compute product or service", + "productName": "AWS Compute Optimizer", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Compute-Optimizer_48.svg" + }, + { + "id": "aws:aws-compute-optimizer-management-tools", + "subject": "Management Tools product or service", + "productName": "AWS Compute Optimizer", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Compute-Optimizer_48.svg" + }, + { + "id": "aws:aws-config", + "subject": "Management Tools product or service", + "productName": "AWS Config", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Config_48.svg" + }, + { + "id": "aws:aws-console-mobile-application", + "subject": "Management Tools product or service", + "productName": "AWS Console Mobile Application", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Console-Mobile-Application_48.svg" + }, + { + "id": "aws:aws-control-tower", + "subject": "Management Tools product or service", + "productName": "AWS Control Tower", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Control-Tower_48.svg" + }, + { + "id": "aws:aws-cost-and-usage-report", + "subject": "Cloud Financial Management product or service", + "productName": "AWS Cost and Usage Report", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_AWS-Cost-and-Usage-Report_48.svg" + }, + { + "id": "aws:aws-cost-explorer", + "subject": "Cloud Financial Management product or service", + "productName": "AWS Cost Explorer", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_AWS-Cost-Explorer_48.svg" + }, + { + "id": "aws:aws-data-exchange", + "subject": "Analytics product or service", + "productName": "AWS Data Exchange", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Data-Exchange_48.svg" + }, + { + "id": "aws:aws-data-transfer-terminal", + "subject": "Migration Modernization product or service", + "productName": "AWS Data Transfer Terminal", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Data-Transfer-Terminal_48.svg" + }, + { + "id": "aws:aws-database-migration-service", + "subject": "Databases product or service", + "productName": "AWS Database Migration Service", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_AWS-Database-Migration-Service_48.svg" + }, + { + "id": "aws:aws-datasync", + "subject": "Migration Modernization product or service", + "productName": "AWS DataSync", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-DataSync_48.svg" + }, + { + "id": "aws:aws-deadline-cloud", + "subject": "Media Services product or service", + "productName": "AWS Deadline Cloud", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Deadline-Cloud_48.svg" + }, + { + "id": "aws:aws-deep-learning-amis", + "subject": "Artificial Intelligence product or service", + "productName": "AWS Deep Learning AMIs", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-Deep-Learning-AMIs_48.svg" + }, + { + "id": "aws:aws-deep-learning-containers", + "subject": "Artificial Intelligence product or service", + "productName": "AWS Deep Learning Containers", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-Deep-Learning-Containers_48.svg" + }, + { + "id": "aws:aws-deepracer", + "subject": "Artificial Intelligence product or service", + "productName": "AWS DeepRacer", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-DeepRacer_48.svg" + }, + { + "id": "aws:aws-device-farm", + "subject": "Front End Web Mobile product or service", + "productName": "AWS Device Farm", + "recommendedNodeKind": "service", + "category": "Front End Web Mobile", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Front-End-Web-Mobile/48/Arch_AWS-Device-Farm_48.svg" + }, + { + "id": "aws:aws-devops-agent", + "subject": "Management Tools product or service", + "productName": "AWS DevOps Agent", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-DevOps-Agent_48.svg" + }, + { + "id": "aws:aws-direct-connect", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Direct Connect", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Direct-Connect_48.svg" + }, + { + "id": "aws:aws-directory-service", + "subject": "Security Identity product or service", + "productName": "AWS Directory Service", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Directory-Service_48.svg" + }, + { + "id": "aws:aws-distro-for-opentelemetry", + "subject": "Management Tools product or service", + "productName": "AWS Distro for OpenTelemetry", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Distro-for-OpenTelemetry_48.svg" + }, + { + "id": "aws:aws-elastic-beanstalk", + "subject": "Compute product or service", + "productName": "AWS Elastic Beanstalk", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Elastic-Beanstalk_48.svg" + }, + { + "id": "aws:aws-elastic-disaster-recovery", + "subject": "Storage product or service", + "productName": "AWS Elastic Disaster Recovery", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_AWS-Elastic-Disaster-Recovery_48.svg" + }, + { + "id": "aws:aws-elemental-appliances-and-software", + "subject": "Media Services product or service", + "productName": "AWS Elemental Appliances & Software", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Appliances-&-Software_48.svg" + }, + { + "id": "aws:aws-elemental-conductor", + "subject": "Media Services product or service", + "productName": "AWS Elemental Conductor", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Conductor_48.svg" + }, + { + "id": "aws:aws-elemental-delta", + "subject": "Media Services product or service", + "productName": "AWS Elemental Delta", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Delta_48.svg" + }, + { + "id": "aws:aws-elemental-inference", + "subject": "Artificial Intelligence product or service", + "productName": "AWS Elemental Inference", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-Elemental-Inference_48.svg" + }, + { + "id": "aws:aws-elemental-link", + "subject": "Media Services product or service", + "productName": "AWS Elemental Link", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Link_48.svg" + }, + { + "id": "aws:aws-elemental-live", + "subject": "Media Services product or service", + "productName": "AWS Elemental Live", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Live_48.svg" + }, + { + "id": "aws:aws-elemental-mediaconnect", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaConnect", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaConnect_48.svg" + }, + { + "id": "aws:aws-elemental-mediaconvert", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaConvert", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaConvert_48.svg" + }, + { + "id": "aws:aws-elemental-medialive", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaLive", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaLive_48.svg" + }, + { + "id": "aws:aws-elemental-mediapackage", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaPackage", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaPackage_48.svg" + }, + { + "id": "aws:aws-elemental-mediastore", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaStore", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaStore_48.svg" + }, + { + "id": "aws:aws-elemental-mediatailor", + "subject": "Media Services product or service", + "productName": "AWS Elemental MediaTailor", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-MediaTailor_48.svg" + }, + { + "id": "aws:aws-elemental-server", + "subject": "Media Services product or service", + "productName": "AWS Elemental Server", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Elemental-Server_48.svg" + }, + { + "id": "aws:aws-end-user-messaging", + "subject": "Business Applications product or service", + "productName": "AWS End User Messaging", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_AWS-End-User-Messaging_48.svg" + }, + { + "id": "aws:aws-entity-resolution", + "subject": "Analytics product or service", + "productName": "AWS Entity Resolution", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Entity-Resolution_48.svg" + }, + { + "id": "aws:aws-express-workflows", + "subject": "Application Integration product or service", + "productName": "AWS Express Workflows", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_AWS-Express-Workflows_48.svg" + }, + { + "id": "aws:aws-fargate", + "subject": "Containers product or service", + "productName": "AWS Fargate", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_AWS-Fargate_48.svg" + }, + { + "id": "aws:aws-fault-injection-service", + "subject": "Developer Tools product or service", + "productName": "AWS Fault Injection Service", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Fault-Injection-Service_48.svg" + }, + { + "id": "aws:aws-finops-agent", + "subject": "Cloud Financial Management product or service", + "productName": "AWS FinOps Agent", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_AWS-FinOps-Agent_48.svg" + }, + { + "id": "aws:aws-firewall-manager", + "subject": "Security Identity product or service", + "productName": "AWS Firewall Manager", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Firewall-Manager_48.svg" + }, + { + "id": "aws:aws-global-accelerator", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Global Accelerator", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Global-Accelerator_48.svg" + }, + { + "id": "aws:aws-glue", + "subject": "Analytics product or service", + "productName": "AWS Glue", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Glue_48.svg" + }, + { + "id": "aws:aws-glue-databrew", + "subject": "Analytics product or service", + "productName": "AWS Glue DataBrew", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Glue-DataBrew_48.svg" + }, + { + "id": "aws:aws-ground-station", + "subject": "Satellite product or service", + "productName": "AWS Ground Station", + "recommendedNodeKind": "service", + "category": "Satellite", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Satellite/48/Arch_AWS-Ground-Station_48.svg" + }, + { + "id": "aws:aws-health-dashboard", + "subject": "Management Tools product or service", + "productName": "AWS Health Dashboard", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Health-Dashboard_48.svg" + }, + { + "id": "aws:aws-healthimaging", + "subject": "Artificial Intelligence product or service", + "productName": "AWS HealthImaging", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-HealthImaging_48.svg" + }, + { + "id": "aws:aws-healthlake", + "subject": "Artificial Intelligence product or service", + "productName": "AWS HealthLake", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-HealthLake_48.svg" + }, + { + "id": "aws:aws-healthomics", + "subject": "Artificial Intelligence product or service", + "productName": "AWS HealthOmics", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-HealthOmics_48.svg" + }, + { + "id": "aws:aws-healthscribe", + "subject": "Artificial Intelligence product or service", + "productName": "AWS HealthScribe", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-HealthScribe_48.svg" + }, + { + "id": "aws:aws-iam-identity-center", + "subject": "Security Identity product or service", + "productName": "AWS IAM Identity Center", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-IAM-Identity-Center_48.svg" + }, + { + "id": "aws:aws-identity-and-access-management", + "subject": "Security Identity product or service", + "productName": "AWS Identity and Access Management", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Identity-and-Access-Management_48.svg" + }, + { + "id": "aws:aws-infrastructure-composer", + "subject": "Developer Tools product or service", + "productName": "AWS Infrastructure Composer", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Infrastructure-Composer_48.svg" + }, + { + "id": "aws:aws-interconnect", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Interconnect", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Interconnect_48.svg" + }, + { + "id": "aws:aws-iot-core", + "subject": "Internet of Things product or service", + "productName": "AWS IoT Core", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-Core_48.svg" + }, + { + "id": "aws:aws-iot-device-defender", + "subject": "Internet of Things product or service", + "productName": "AWS IoT Device Defender", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-Device-Defender_48.svg" + }, + { + "id": "aws:aws-iot-device-management", + "subject": "Internet of Things product or service", + "productName": "AWS IoT Device Management", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-Device-Management_48.svg" + }, + { + "id": "aws:aws-iot-events", + "subject": "Internet of Things product or service", + "productName": "AWS IoT Events", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-Events_48.svg" + }, + { + "id": "aws:aws-iot-expresslink", + "subject": "Internet of Things product or service", + "productName": "AWS IoT ExpressLink", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-ExpressLink_48.svg" + }, + { + "id": "aws:aws-iot-fleetwise", + "subject": "Internet of Things product or service", + "productName": "AWS IoT FleetWise", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-FleetWise_48.svg" + }, + { + "id": "aws:aws-iot-greengrass", + "subject": "Internet of Things product or service", + "productName": "AWS IoT Greengrass", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-Greengrass_48.svg" + }, + { + "id": "aws:aws-iot-sitewise", + "subject": "Internet of Things product or service", + "productName": "AWS IoT SiteWise", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-SiteWise_48.svg" + }, + { + "id": "aws:aws-iot-twinmaker", + "subject": "Internet of Things product or service", + "productName": "AWS IoT TwinMaker", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_AWS-IoT-TwinMaker_48.svg" + }, + { + "id": "aws:aws-iq", + "subject": "Customer Enablement product or service", + "productName": "AWS IQ", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-IQ_48.svg" + }, + { + "id": "aws:aws-key-management-service", + "subject": "Security Identity product or service", + "productName": "AWS Key Management Service", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Key-Management-Service_48.svg" + }, + { + "id": "aws:aws-lake-formation", + "subject": "Analytics product or service", + "productName": "AWS Lake Formation", + "recommendedNodeKind": "service", + "category": "Analytics", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Analytics/48/Arch_AWS-Lake-Formation_48.svg" + }, + { + "id": "aws:aws-launch-wizard", + "subject": "Management Tools product or service", + "productName": "AWS Launch Wizard", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Launch-Wizard_48.svg" + }, + { + "id": "aws:aws-license-manager", + "subject": "Management Tools product or service", + "productName": "AWS License Manager", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-License-Manager_48.svg" + }, + { + "id": "aws:aws-local-zones", + "subject": "Compute product or service", + "productName": "AWS Local Zones", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Local-Zones_48.svg" + }, + { + "id": "aws:aws-mainframe-modernization", + "subject": "Migration Modernization product or service", + "productName": "AWS Mainframe Modernization", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Mainframe-Modernization_48.svg" + }, + { + "id": "aws:aws-managed-services", + "subject": "Customer Enablement product or service", + "productName": "AWS Managed Services", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-Managed-Services_48.svg" + }, + { + "id": "aws:aws-management-console", + "subject": "Management Tools product or service", + "productName": "AWS Management Console", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Management-Console_48.svg" + }, + { + "id": "aws:aws-marketplace-dark", + "subject": "General Icons product or service", + "productName": "AWS Marketplace_Dark", + "recommendedNodeKind": "service", + "category": "General Icons", + "archivePath": "Architecture-Service-Icons_07312026/Arch_General-Icons/48/Arch_AWS-Marketplace_Dark_48.svg" + }, + { + "id": "aws:aws-marketplace-light", + "subject": "General Icons product or service", + "productName": "AWS Marketplace_Light", + "recommendedNodeKind": "service", + "category": "General Icons", + "archivePath": "Architecture-Service-Icons_07312026/Arch_General-Icons/48/Arch_AWS-Marketplace_Light_48.svg" + }, + { + "id": "aws:aws-migration-evaluator", + "subject": "Migration Modernization product or service", + "productName": "AWS Migration Evaluator", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Migration-Evaluator_48.svg" + }, + { + "id": "aws:aws-network-firewall", + "subject": "Security Identity product or service", + "productName": "AWS Network Firewall", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Network-Firewall_48.svg" + }, + { + "id": "aws:aws-neuron", + "subject": "Artificial Intelligence product or service", + "productName": "AWS Neuron", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-Neuron_48.svg" + }, + { + "id": "aws:aws-nitro-enclaves", + "subject": "Compute product or service", + "productName": "AWS Nitro Enclaves", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Nitro-Enclaves_48.svg" + }, + { + "id": "aws:aws-organizations", + "subject": "Management Tools product or service", + "productName": "AWS Organizations", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Organizations_48.svg" + }, + { + "id": "aws:aws-outposts-family", + "subject": "Compute product or service", + "productName": "AWS Outposts family", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Outposts-family_48.svg" + }, + { + "id": "aws:aws-outposts-rack", + "subject": "Compute product or service", + "productName": "AWS Outposts rack", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Outposts-rack_48.svg" + }, + { + "id": "aws:aws-outposts-servers", + "subject": "Compute product or service", + "productName": "AWS Outposts servers", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Outposts-servers_48.svg" + }, + { + "id": "aws:aws-panorama", + "subject": "Artificial Intelligence product or service", + "productName": "AWS Panorama", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_AWS-Panorama_48.svg" + }, + { + "id": "aws:aws-parallel-cluster", + "subject": "Compute product or service", + "productName": "AWS Parallel Cluster", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Parallel-Cluster_48.svg" + }, + { + "id": "aws:aws-parallel-computing-service", + "subject": "Compute product or service", + "productName": "AWS Parallel Computing Service", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Parallel-Computing-Service_48.svg" + }, + { + "id": "aws:aws-partner-central", + "subject": "Management Tools product or service", + "productName": "AWS Partner Central", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Partner-Central_48.svg" + }, + { + "id": "aws:aws-payment-cryptography", + "subject": "Security Identity product or service", + "productName": "AWS Payment Cryptography", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Payment-Cryptography_48.svg" + }, + { + "id": "aws:aws-private-certificate-authority", + "subject": "Security Identity product or service", + "productName": "AWS Private Certificate Authority", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Private-Certificate-Authority_48.svg" + }, + { + "id": "aws:aws-privatelink", + "subject": "Networking Content Delivery product or service", + "productName": "AWS PrivateLink", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-PrivateLink_48.svg" + }, + { + "id": "aws:aws-professional-services", + "subject": "Customer Enablement product or service", + "productName": "AWS Professional Services", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-Professional-Services_48.svg" + }, + { + "id": "aws:aws-proton", + "subject": "Management Tools product or service", + "productName": "AWS Proton", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Proton_48.svg" + }, + { + "id": "aws:aws-repost", + "subject": "Customer Enablement product or service", + "productName": "AWS rePost", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-rePost_48.svg" + }, + { + "id": "aws:aws-repost-private", + "subject": "Customer Enablement product or service", + "productName": "AWS rePost Private", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-rePost-Private_48.svg" + }, + { + "id": "aws:aws-resilience-hub", + "subject": "Management Tools product or service", + "productName": "AWS Resilience Hub", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Resilience-Hub_48.svg" + }, + { + "id": "aws:aws-resource-access-manager", + "subject": "Security Identity product or service", + "productName": "AWS Resource Access Manager", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Resource-Access-Manager_48.svg" + }, + { + "id": "aws:aws-resource-explorer", + "subject": "Management Tools product or service", + "productName": "AWS Resource Explorer", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Resource-Explorer_48.svg" + }, + { + "id": "aws:aws-rtb-fabric", + "subject": "Networking Content Delivery product or service", + "productName": "AWS RTB Fabric", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-RTB-Fabric_48.svg" + }, + { + "id": "aws:aws-secrets-manager", + "subject": "Security Identity product or service", + "productName": "AWS Secrets Manager", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Secrets-Manager_48.svg" + }, + { + "id": "aws:aws-security-agent", + "subject": "Security Identity product or service", + "productName": "AWS Security Agent", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Security-Agent_48.svg" + }, + { + "id": "aws:aws-security-hub", + "subject": "Security Identity product or service", + "productName": "AWS Security Hub", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Security-Hub_48.svg" + }, + { + "id": "aws:aws-security-incident-response", + "subject": "Security Identity product or service", + "productName": "AWS Security Incident Response", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Security-Incident-Response_48.svg" + }, + { + "id": "aws:aws-serverless-application-repository", + "subject": "Compute product or service", + "productName": "AWS Serverless Application Repository", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Serverless-Application-Repository_48.svg" + }, + { + "id": "aws:aws-service-catalog", + "subject": "Management Tools product or service", + "productName": "AWS Service Catalog", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Service-Catalog_48.svg" + }, + { + "id": "aws:aws-service-management-connector", + "subject": "Management Tools product or service", + "productName": "AWS Service Management Connector", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Service-Management-Connector_48.svg" + }, + { + "id": "aws:aws-shield", + "subject": "Security Identity product or service", + "productName": "AWS Shield", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Shield_48.svg" + }, + { + "id": "aws:aws-signer", + "subject": "Security Identity product or service", + "productName": "AWS Signer", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-Signer_48.svg" + }, + { + "id": "aws:aws-simspace-weaver", + "subject": "Compute product or service", + "productName": "AWS SimSpace Weaver", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-SimSpace-Weaver_48.svg" + }, + { + "id": "aws:aws-site-to-site-vpn", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Site to Site VPN", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Site-to-Site-VPN_48.svg" + }, + { + "id": "aws:aws-snowball", + "subject": "Storage product or service", + "productName": "AWS Snowball", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_AWS-Snowball_48.svg" + }, + { + "id": "aws:aws-snowball-edge", + "subject": "Storage product or service", + "productName": "AWS Snowball Edge", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_AWS-Snowball-Edge_48.svg" + }, + { + "id": "aws:aws-step-functions", + "subject": "Application Integration product or service", + "productName": "AWS Step Functions", + "recommendedNodeKind": "service", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_AWS-Step-Functions_48.svg" + }, + { + "id": "aws:aws-storage-gateway", + "subject": "Storage product or service", + "productName": "AWS Storage Gateway", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_AWS-Storage-Gateway_48.svg" + }, + { + "id": "aws:aws-supply-chain", + "subject": "Business Applications product or service", + "productName": "AWS Supply Chain", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_AWS-Supply-Chain_48.svg" + }, + { + "id": "aws:aws-support", + "subject": "Customer Enablement product or service", + "productName": "AWS Support", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-Support_48.svg" + }, + { + "id": "aws:aws-sustainability", + "subject": "Management Tools product or service", + "productName": "AWS Sustainability", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Sustainability_48.svg" + }, + { + "id": "aws:aws-systems-manager", + "subject": "Management Tools product or service", + "productName": "AWS Systems Manager", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Systems-Manager_48.svg" + }, + { + "id": "aws:aws-telco-network-builder", + "subject": "Management Tools product or service", + "productName": "AWS Telco Network Builder", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Telco-Network-Builder_48.svg" + }, + { + "id": "aws:aws-thinkbox-deadline", + "subject": "Media Services product or service", + "productName": "AWS Thinkbox Deadline", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Thinkbox-Deadline_48.svg" + }, + { + "id": "aws:aws-thinkbox-frost", + "subject": "Media Services product or service", + "productName": "AWS Thinkbox Frost", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Thinkbox-Frost_48.svg" + }, + { + "id": "aws:aws-thinkbox-krakatoa", + "subject": "Media Services product or service", + "productName": "AWS Thinkbox Krakatoa", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Thinkbox-Krakatoa_48.svg" + }, + { + "id": "aws:aws-thinkbox-stoke", + "subject": "Media Services product or service", + "productName": "AWS Thinkbox Stoke", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Thinkbox-Stoke_48.svg" + }, + { + "id": "aws:aws-thinkbox-xmesh", + "subject": "Media Services product or service", + "productName": "AWS Thinkbox XMesh", + "recommendedNodeKind": "service", + "category": "Media Services", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Media-Services/48/Arch_AWS-Thinkbox-XMesh_48.svg" + }, + { + "id": "aws:aws-tools-and-sdks", + "subject": "Developer Tools product or service", + "productName": "AWS Tools and SDKs", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-Tools-and-SDKs_48.svg" + }, + { + "id": "aws:aws-training-certification", + "subject": "Customer Enablement product or service", + "productName": "AWS Training Certification", + "recommendedNodeKind": "service", + "category": "Customer Enablement", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Customer-Enablement/48/Arch_AWS-Training-Certification_48.svg" + }, + { + "id": "aws:aws-transfer-family", + "subject": "Migration Modernization product or service", + "productName": "AWS Transfer Family", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Transfer-Family_48.svg" + }, + { + "id": "aws:aws-transform", + "subject": "Migration Modernization product or service", + "productName": "AWS Transform", + "recommendedNodeKind": "service", + "category": "Migration Modernization", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Migration-Modernization/48/Arch_AWS-Transform_48.svg" + }, + { + "id": "aws:aws-transit-gateway", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Transit Gateway", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Transit-Gateway_48.svg" + }, + { + "id": "aws:aws-trusted-advisor", + "subject": "Management Tools product or service", + "productName": "AWS Trusted Advisor", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Trusted-Advisor_48.svg" + }, + { + "id": "aws:aws-user-notifications", + "subject": "Management Tools product or service", + "productName": "AWS User Notifications", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-User-Notifications_48.svg" + }, + { + "id": "aws:aws-verified-access", + "subject": "Networking Content Delivery product or service", + "productName": "AWS Verified Access", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_AWS-Verified-Access_48.svg" + }, + { + "id": "aws:aws-waf", + "subject": "Security Identity product or service", + "productName": "AWS WAF", + "recommendedNodeKind": "service", + "category": "Security Identity", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Security-Identity/48/Arch_AWS-WAF_48.svg" + }, + { + "id": "aws:aws-wavelength", + "subject": "Compute product or service", + "productName": "AWS Wavelength", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Wavelength_48.svg" + }, + { + "id": "aws:aws-well-architected-tool", + "subject": "Management Tools product or service", + "productName": "AWS Well Architected Tool", + "recommendedNodeKind": "service", + "category": "Management Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Management-Tools/48/Arch_AWS-Well-Architected-Tool_48.svg" + }, + { + "id": "aws:aws-wickr", + "subject": "Business Applications product or service", + "productName": "AWS Wickr", + "recommendedNodeKind": "service", + "category": "Business Applications", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Business-Applications/48/Arch_AWS-Wickr_48.svg" + }, + { + "id": "aws:aws-x-ray", + "subject": "Developer Tools product or service", + "productName": "AWS X Ray", + "recommendedNodeKind": "service", + "category": "Developer Tools", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Developer-Tools/48/Arch_AWS-X-Ray_48.svg" + }, + { + "id": "aws:bottlerocket", + "subject": "Compute product or service", + "productName": "Bottlerocket", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Bottlerocket_48.svg" + }, + { + "id": "aws:dynamodb", + "subject": "Databases product or service", + "productName": "Amazon DynamoDB", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-DynamoDB_48.svg" + }, + { + "id": "aws:ec2", + "subject": "Compute product or service", + "productName": "Amazon Elastic Compute Cloud (Amazon EC2)", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-EC2_48.svg" + }, + { + "id": "aws:eks", + "subject": "Containers product or service", + "productName": "Amazon Elastic Kubernetes Service (Amazon EKS)", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-Elastic-Kubernetes-Service_48.svg" + }, + { + "id": "aws:elastic-fabric-adapter", + "subject": "Compute product or service", + "productName": "Elastic Fabric Adapter", + "recommendedNodeKind": "service", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Elastic-Fabric-Adapter_48.svg" + }, + { + "id": "aws:elastic-load-balancing", + "subject": "Networking Content Delivery product or service", + "productName": "Elastic Load Balancing", + "recommendedNodeKind": "service", + "category": "Networking Content Delivery", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Networking-Content-Delivery/48/Arch_Elastic-Load-Balancing_48.svg" + }, + { + "id": "aws:freertos", + "subject": "Internet of Things product or service", + "productName": "FreeRTOS", + "recommendedNodeKind": "service", + "category": "Internet of Things", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Internet-of-Things/48/Arch_FreeRTOS_48.svg" + }, + { + "id": "aws:lambda", + "subject": "Compute product or service", + "productName": "AWS Lambda", + "recommendedNodeKind": "function", + "category": "Compute", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Lambda_48.svg" + }, + { + "id": "aws:open-3d-engine", + "subject": "Games product or service", + "productName": "Open 3D Engine", + "recommendedNodeKind": "service", + "category": "Games", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Games/48/Arch_Open-3D-Engine_48.svg" + }, + { + "id": "aws:oracle-database-at-aws", + "subject": "Databases product or service", + "productName": "Oracle Database at AWS", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Oracle-Database-at-AWS_48.svg" + }, + { + "id": "aws:pytorch-on-aws", + "subject": "Artificial Intelligence product or service", + "productName": "PyTorch on AWS", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_PyTorch-on-AWS_48.svg" + }, + { + "id": "aws:rds", + "subject": "Databases product or service", + "productName": "Amazon Relational Database Service (Amazon RDS)", + "recommendedNodeKind": "database", + "category": "Databases", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-RDS_48.svg" + }, + { + "id": "aws:red-hat-openshift-service-on-aws", + "subject": "Containers product or service", + "productName": "Red Hat OpenShift Service on AWS", + "recommendedNodeKind": "service", + "category": "Containers", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Red-Hat-OpenShift-Service-on-AWS_48.svg" + }, + { + "id": "aws:reserved-instance-reporting", + "subject": "Cloud Financial Management product or service", + "productName": "Reserved Instance Reporting", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_Reserved-Instance-Reporting_48.svg" + }, + { + "id": "aws:s3", + "subject": "Storage product or service", + "productName": "Amazon Simple Storage Service (Amazon S3)", + "recommendedNodeKind": "storage", + "category": "Storage", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-Simple-Storage-Service_48.svg" + }, + { + "id": "aws:savings-plans", + "subject": "Cloud Financial Management product or service", + "productName": "Savings Plans", + "recommendedNodeKind": "storage", + "category": "Cloud Financial Management", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Cloud-Financial-Management/48/Arch_Savings-Plans_48.svg" + }, + { + "id": "aws:sqs", + "subject": "Application Integration product or service", + "productName": "Amazon Simple Queue Service (Amazon SQS)", + "recommendedNodeKind": "queue", + "category": "Application Integration", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-Simple-Queue-Service_48.svg" + }, + { + "id": "aws:tensorflow-on-aws", + "subject": "Artificial Intelligence product or service", + "productName": "TensorFlow on AWS", + "recommendedNodeKind": "service", + "category": "Artificial Intelligence", + "archivePath": "Architecture-Service-Icons_07312026/Arch_Artificial-Intelligence/48/Arch_TensorFlow-on-AWS_48.svg" + } + ] +} diff --git a/catalogs/azure.json b/catalogs/azure.json new file mode 100644 index 0000000..b94f363 --- /dev/null +++ b/catalogs/azure.json @@ -0,0 +1,5166 @@ +{ + "catalogVersion": "1.0", + "packVersion": "0.2.0", + "provider": { + "id": "azure", + "name": "Microsoft Azure" + }, + "source": { + "pageUrl": "https://learn.microsoft.com/azure/architecture/icons/", + "archiveUrl": "https://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V24.zip", + "archiveSha256": "sha256:921594ccd1bf3d9c0a1bd7b6d924e050551a59342f2b353bb74bdcf761c35141", + "release": "Azure_Public_Service_Icons_V24", + "retrievedAt": "2026-09-04", + "termsUrl": "https://learn.microsoft.com/azure/architecture/icons/", + "termsReviewedAt": "2026-09-04", + "reviewAfter": "2026-12-03", + "copyright": "Copyright Microsoft Corporation", + "licenseId": "LicenseRef-Microsoft-Azure-Architecture-Icons-Terms", + "archiveLicenseIncluded": true + }, + "additionalSources": [], + "rights": { + "termsAcceptanceRequired": true, + "permittedOutputs": [ + "architecture-diagram", + "training-material", + "documentation" + ], + "redistribution": { + "cargo": false, + "npm": false, + "wasm": false, + "webAsset": false, + "nativeBinary": false, + "generatedOutput": true + }, + "processing": { + "localOnly": true, + "automaticDownload": false, + "serverUpload": false, + "preserveColors": true, + "preserveGeometry": true, + "productNameNearby": true + }, + "modificationPolicy": "visual-preservation-only" + }, + "notice": { + "attribution": "Azure architecture icons are owned by Microsoft Corporation.", + "termsSummary": "Use is limited to architecture diagrams, training materials, and documentation under the terms included in the official Azure icon archive.", + "nonEndorsement": "Microsoft does not sponsor or endorse this diagram or Stack." + }, + "icons": [ + { + "id": "azure:030777508-icon-service-service-group-relationships", + "subject": "new icons product or service", + "productName": "030777508 icon service Service Group Relationships", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/030777508 -icon-service-Service-Group-Relationships.svg" + }, + { + "id": "azure:abs-member", + "subject": "blockchain product or service", + "productName": "ABS Member", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10374-icon-service-ABS-Member.svg" + }, + { + "id": "azure:active-directory-connect-health", + "subject": "identity product or service", + "productName": "Active Directory Connect Health", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10224-icon-service-Active-Directory-Connect-Health.svg" + }, + { + "id": "azure:activity-log", + "subject": "management + governance product or service", + "productName": "Activity Log", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00007-icon-service-Activity-Log.svg" + }, + { + "id": "azure:administrative-units", + "subject": "identity product or service", + "productName": "Administrative Units", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/00919-icon-service-Administrative-Units.svg" + }, + { + "id": "azure:advisor", + "subject": "management + governance product or service", + "productName": "Advisor", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00003-icon-service-Advisor.svg" + }, + { + "id": "azure:agentic-web-apps", + "subject": "new icons product or service", + "productName": "Agentic Web Apps", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/034296882-icon-service-Agentic-Web-Apps.svg" + }, + { + "id": "azure:ai-at-edge", + "subject": "hybrid + multicloud product or service", + "productName": "AI at Edge", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03687-icon-service-AI-at-Edge.svg" + }, + { + "id": "azure:ai-foundry", + "subject": "ai + machine learning product or service", + "productName": "AI Foundry", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/035746832-icon-service-AI-Foundry.svg" + }, + { + "id": "azure:ai-gateway", + "subject": "new icons product or service", + "productName": "AI Gateway", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/037838045-icon-service-AI-Gateway.svg" + }, + { + "id": "azure:ai-studio", + "subject": "ai + machine learning product or service", + "productName": "AI Studio", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03513-icon-service-AI-Studio.svg" + }, + { + "id": "azure:aks", + "subject": "containers product or service", + "productName": "Azure Kubernetes Service (AKS)", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/10023-icon-service-Kubernetes-Services.svg" + }, + { + "id": "azure:aks-automatic", + "subject": "compute product or service", + "productName": "AKS Automatic", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/03543-icon-service-AKS-Automatic.svg" + }, + { + "id": "azure:aks-istio", + "subject": "other product or service", + "productName": "AKS Istio", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03399-icon-service-AKS-Istio.svg" + }, + { + "id": "azure:aks-network-policy", + "subject": "containers product or service", + "productName": "AKS Network Policy", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/032487601-icon-service-AKS-Network-Policy.svg" + }, + { + "id": "azure:alerts", + "subject": "management + governance product or service", + "productName": "Alerts", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00002-icon-service-Alerts.svg" + }, + { + "id": "azure:all-resources", + "subject": "general product or service", + "productName": "All Resources", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10001-icon-service-All-Resources.svg" + }, + { + "id": "azure:analysis-services", + "subject": "analytics product or service", + "productName": "Analysis Services", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10148-icon-service-Analysis-Services.svg" + }, + { + "id": "azure:anomaly-detector", + "subject": "ai + machine learning product or service", + "productName": "Anomaly Detector", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00814-icon-service-Anomaly-Detector.svg" + }, + { + "id": "azure:api-center", + "subject": "web product or service", + "productName": "API Center", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/03291-icon-service-API-Center.svg" + }, + { + "id": "azure:api-connections", + "subject": "devops product or service", + "productName": "API Connections", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/10048-icon-service-API-Connections.svg" + }, + { + "id": "azure:api-management-services", + "subject": "devops product or service", + "productName": "API Management Services", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/10042-icon-service-API-Management-Services.svg" + }, + { + "id": "azure:api-proxy", + "subject": "identity product or service", + "productName": "API Proxy", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02386-icon-service-API-Proxy.svg" + }, + { + "id": "azure:app-compliance-automation", + "subject": "other product or service", + "productName": "App Compliance Automation", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03071-icon-service-App-Compliance-Automation.svg" + }, + { + "id": "azure:app-configuration", + "subject": "integration product or service", + "productName": "App Configuration", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10219-icon-service-App-Configuration.svg" + }, + { + "id": "azure:app-registrations", + "subject": "identity product or service", + "productName": "App Registrations", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10232-icon-service-App-Registrations.svg" + }, + { + "id": "azure:app-service", + "subject": "app services product or service", + "productName": "Azure App Service", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/10035-icon-service-App-Services.svg" + }, + { + "id": "azure:app-service-certificates", + "subject": "app services product or service", + "productName": "App Service Certificates", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/00049-icon-service-App-Service-Certificates.svg" + }, + { + "id": "azure:app-service-domains", + "subject": "app services product or service", + "productName": "App Service Domains", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/00050-icon-service-App-Service-Domains.svg" + }, + { + "id": "azure:app-service-environments", + "subject": "app services product or service", + "productName": "App Service Environments", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/10047-icon-service-App-Service-Environments.svg" + }, + { + "id": "azure:app-service-plans", + "subject": "app services product or service", + "productName": "App Service Plans", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/00046-icon-service-App-Service-Plans.svg" + }, + { + "id": "azure:app-space", + "subject": "web product or service", + "productName": "App Space", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/03397-icon-service-App-Space.svg" + }, + { + "id": "azure:app-space-component", + "subject": "web product or service", + "productName": "App Space Component", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/03595-icon-service-App-Space-Component.svg" + }, + { + "id": "azure:applens", + "subject": "azure ecosystem product or service", + "productName": "Applens", + "recommendedNodeKind": "service", + "category": "azure ecosystem", + "archivePath": "Azure_Public_Service_Icons/Icons/azure ecosystem/02354-icon-service-Applens.svg" + }, + { + "id": "azure:application-gateway-containers", + "subject": "networking product or service", + "productName": "Application Gateway Containers", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03328-icon-service-Application-Gateway-Containers.svg" + }, + { + "id": "azure:application-gateways", + "subject": "networking product or service", + "productName": "Application Gateways", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10076-icon-service-Application-Gateways.svg" + }, + { + "id": "azure:application-group", + "subject": "compute product or service", + "productName": "Application Group", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00329-icon-service-Application-Group.svg" + }, + { + "id": "azure:application-insights", + "subject": "devops product or service", + "productName": "Application Insights", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/00012-icon-service-Application-Insights.svg" + }, + { + "id": "azure:application-security-groups", + "subject": "security product or service", + "productName": "Application Security Groups", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10244-icon-service-Application-Security-Groups.svg" + }, + { + "id": "azure:aquila", + "subject": "other product or service", + "productName": "Aquila", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02625-icon-service-Aquila.svg" + }, + { + "id": "azure:arc-data-services", + "subject": "other product or service", + "productName": "Arc Data services", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02356-icon-service-Arc-Data-services.svg" + }, + { + "id": "azure:arc-kubernetes", + "subject": "hybrid + multicloud product or service", + "productName": "Arc Kubernetes", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/01088-icon-service-Arc-Kubernetes.svg" + }, + { + "id": "azure:arc-machines", + "subject": "management + governance product or service", + "productName": "Arc Machines", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/01710-icon-service-Arc-Machines.svg" + }, + { + "id": "azure:arc-postgresql", + "subject": "other product or service", + "productName": "Arc PostgreSQL ", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01848-icon-service-Arc-PostgreSQL .svg" + }, + { + "id": "azure:arc-sql-managed-instance", + "subject": "other product or service", + "productName": "Arc SQL Managed Instance", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01849-icon-service-Arc-SQL-Managed-Instance.svg" + }, + { + "id": "azure:arc-sql-server", + "subject": "other product or service", + "productName": "Arc SQL Server", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01850-icon-service-Arc-SQL-Server.svg" + }, + { + "id": "azure:atm-multistack", + "subject": "networking product or service", + "productName": "ATM Multistack", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03460-icon-service-ATM-Multistack.svg" + }, + { + "id": "azure:auto-scale", + "subject": "monitor product or service", + "productName": "Auto Scale", + "recommendedNodeKind": "service", + "category": "monitor", + "archivePath": "Azure_Public_Service_Icons/Icons/monitor/10832-icon-service-Auto-Scale.svg" + }, + { + "id": "azure:automanaged-vm", + "subject": "compute product or service", + "productName": "Automanaged VM", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02112-icon-service-Automanaged-VM.svg" + }, + { + "id": "azure:automation-accounts", + "subject": "management + governance product or service", + "productName": "Automation Accounts", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00022-icon-service-Automation-Accounts.svg" + }, + { + "id": "azure:availability-sets", + "subject": "compute product or service", + "productName": "Availability Sets", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10025-icon-service-Availability-Sets.svg" + }, + { + "id": "azure:avs-vm", + "subject": "other product or service", + "productName": "AVS VM", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01846-icon-service-AVS-VM.svg" + }, + { + "id": "azure:azure-a", + "subject": "other product or service", + "productName": "Azure A", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10018-icon-service-Azure-A.svg" + }, + { + "id": "azure:azure-access-point", + "subject": "new icons product or service", + "productName": "Azure Access Point", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/031193085-icon-service-Azure-Access-Point.svg" + }, + { + "id": "azure:azure-ad-b2c", + "subject": "identity product or service", + "productName": "Azure AD B2C", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10228-icon-service-Azure-AD-B2C.svg" + }, + { + "id": "azure:azure-ai-foundry-iq", + "subject": "ai + machine learning product or service", + "productName": "Azure AI Foundry IQ", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470497-icon-service-Azure-AI-Foundry-IQ.svg" + }, + { + "id": "azure:azure-api-for-fhir", + "subject": "integration product or service", + "productName": "Azure API for FHIR", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10212-icon-service-Azure-API-for-FHIR.svg" + }, + { + "id": "azure:azure-app-testing", + "subject": "developer tools product or service", + "productName": "Azure App Testing", + "recommendedNodeKind": "service", + "category": "developer tools", + "archivePath": "Azure_Public_Service_Icons/Icons/developer tools/033805167-icon-service-Azure-App-Testing.svg" + }, + { + "id": "azure:azure-applied-ai-services", + "subject": "ai + machine learning product or service", + "productName": "Azure Applied AI Services", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/02749-icon-service-Azure-Applied-AI-Services.svg" + }, + { + "id": "azure:azure-arc", + "subject": "management + governance product or service", + "productName": "Azure Arc", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00756-icon-service-Azure-Arc.svg" + }, + { + "id": "azure:azure-backup-center", + "subject": "other product or service", + "productName": "Azure Backup Center", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02360-icon-service-Azure-Backup-Center.svg" + }, + { + "id": "azure:azure-blockchain-service", + "subject": "blockchain product or service", + "productName": "Azure Blockchain Service", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10366-icon-service-Azure-Blockchain-Service.svg" + }, + { + "id": "azure:azure-center-for-sap", + "subject": "other product or service", + "productName": "Azure Center for SAP", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03090-icon-service-Azure-Center-for-SAP.svg" + }, + { + "id": "azure:azure-chaos-studio", + "subject": "other product or service", + "productName": "Azure Chaos Studio", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02223-icon-service-Azure-Chaos-Studio.svg" + }, + { + "id": "azure:azure-cloud-shell", + "subject": "other product or service", + "productName": "Azure Cloud Shell", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00559-icon-service-Azure-Cloud-Shell.svg" + }, + { + "id": "azure:azure-communication-services", + "subject": "other product or service", + "productName": "Azure Communication Services", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00968-icon-service-Azure-Communication-Services.svg" + }, + { + "id": "azure:azure-communications-gateway", + "subject": "networking product or service", + "productName": "Azure Communications Gateway", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03311-icon-service-Azure-Communications-Gateway.svg" + }, + { + "id": "azure:azure-compute-galleries", + "subject": "compute product or service", + "productName": "Azure Compute Galleries", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02864-icon-service-Azure-Compute-Galleries.svg" + }, + { + "id": "azure:azure-consumption-commitment", + "subject": "other product or service", + "productName": "Azure Consumption Commitment", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03495-icon-service-Azure-Consumption-Commitment.svg" + }, + { + "id": "azure:azure-container-storage", + "subject": "containers product or service", + "productName": "Azure Container Storage", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/03401-icon-service-Azure-Container-Storage.svg" + }, + { + "id": "azure:azure-cosmos-db", + "subject": "databases product or service", + "productName": "Azure Cosmos DB", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10121-icon-service-Azure-Cosmos-DB.svg" + }, + { + "id": "azure:azure-data-catalog", + "subject": "integration product or service", + "productName": "Azure Data Catalog", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10216-icon-service-Azure-Data-Catalog.svg" + }, + { + "id": "azure:azure-data-explorer-clusters", + "subject": "analytics product or service", + "productName": "Azure Data Explorer Clusters", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10145-icon-service-Azure-Data-Explorer-Clusters.svg" + }, + { + "id": "azure:azure-data-sharing", + "subject": "new icons product or service", + "productName": "Azure Data Sharing", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/035824068-icon-service-Azure-Data-Sharing.svg" + }, + { + "id": "azure:azure-data-transfer", + "subject": "new icons product or service", + "productName": "Azure Data Transfer", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/033740592-icon-service-Azure-Data-Transfer.svg" + }, + { + "id": "azure:azure-database-mariadb-server", + "subject": "databases product or service", + "productName": "Azure Database MariaDB Server", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10123-icon-service-Azure-Database-MariaDB-Server.svg" + }, + { + "id": "azure:azure-database-migration-services", + "subject": "databases product or service", + "productName": "Azure Database Migration Services", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10133-icon-service-Azure-Database-Migration-Services.svg" + }, + { + "id": "azure:azure-database-mysql-server", + "subject": "databases product or service", + "productName": "Azure Database MySQL Server", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10122-icon-service-Azure-Database-MySQL-Server.svg" + }, + { + "id": "azure:azure-database-postgresql-server", + "subject": "databases product or service", + "productName": "Azure Database PostgreSQL Server", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10131-icon-service-Azure-Database-PostgreSQL-Server.svg" + }, + { + "id": "azure:azure-database-postgresql-server-group", + "subject": "databases product or service", + "productName": "Azure Database PostgreSQL Server Group", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/02827-icon-service-Azure-Database-PostgreSQL-Server-Group.svg" + }, + { + "id": "azure:azure-databox-gateway", + "subject": "integration product or service", + "productName": "Azure Databox Gateway", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/00691-icon-service-Azure-Databox-Gateway.svg" + }, + { + "id": "azure:azure-databricks", + "subject": "analytics product or service", + "productName": "Azure Databricks", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10787-icon-service-Azure-Databricks.svg" + }, + { + "id": "azure:azure-deployment-environments", + "subject": "other product or service", + "productName": "Azure Deployment Environments", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03251-icon-service-Azure-Deployment-Environments.svg" + }, + { + "id": "azure:azure-dev-tunnels", + "subject": "other product or service", + "productName": "Azure Dev Tunnels", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03308-icon-service-Azure-Dev-Tunnels.svg" + }, + { + "id": "azure:azure-devops", + "subject": "devops product or service", + "productName": "Azure DevOps", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/10261-icon-service-Azure-DevOps.svg" + }, + { + "id": "azure:azure-documentdb", + "subject": "databases product or service", + "productName": "Azure DocumentDB", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/035656437-icon-service-Azure-DocumentDB.svg" + }, + { + "id": "azure:azure-edge-hardware-center", + "subject": "other product or service", + "productName": "Azure Edge Hardware Center", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02810-icon-service-Azure-Edge-Hardware-Center.svg" + }, + { + "id": "azure:azure-enclaves", + "subject": "other product or service", + "productName": "Azure Enclaves", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03394-icon-service-Azure-Enclaves.svg" + }, + { + "id": "azure:azure-experimentation-studio", + "subject": "ai + machine learning product or service", + "productName": "Azure Experimentation Studio", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/01239-icon-service-Azure-Experimentation-Studio.svg" + }, + { + "id": "azure:azure-fileshares", + "subject": "storage product or service", + "productName": "Azure Fileshares", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10400-icon-service-Azure-Fileshares.svg" + }, + { + "id": "azure:azure-firewall-manager", + "subject": "networking product or service", + "productName": "Azure Firewall Manager", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/00271-icon-service-Azure-Firewall-Manager.svg" + }, + { + "id": "azure:azure-firewall-policy", + "subject": "networking product or service", + "productName": "Azure Firewall Policy", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/00272-icon-service-Azure-Firewall-Policy.svg" + }, + { + "id": "azure:azure-hcp-cache", + "subject": "storage product or service", + "productName": "Azure HCP Cache", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/00776-icon-service-Azure-HCP-Cache.svg" + }, + { + "id": "azure:azure-hpc-workbenches", + "subject": "other product or service", + "productName": "Azure HPC Workbenches", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02518-icon-service-Azure-HPC-Workbenches.svg" + }, + { + "id": "azure:azure-hybrid-center", + "subject": "azure ecosystem product or service", + "productName": "Azure Hybrid Center", + "recommendedNodeKind": "service", + "category": "azure ecosystem", + "archivePath": "Azure_Public_Service_Icons/Icons/azure ecosystem/02573-icon-service-Azure-Hybrid-Center.svg" + }, + { + "id": "azure:azure-information-protection", + "subject": "identity product or service", + "productName": "Azure Information Protection", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10229-icon-service-Azure-Information-Protection.svg" + }, + { + "id": "azure:azure-iot-operations", + "subject": "iot product or service", + "productName": "Azure IoT Operations", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/03485-icon-service-Azure-IoT-Operations.svg" + }, + { + "id": "azure:azure-lighthouse", + "subject": "management + governance product or service", + "productName": "Azure Lighthouse", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00471-icon-service-Azure-Lighthouse.svg" + }, + { + "id": "azure:azure-linux", + "subject": "compute product or service", + "productName": "Azure Linux", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/03645-icon-service-Azure-Linux.svg" + }, + { + "id": "azure:azure-load-testing", + "subject": "other product or service", + "productName": "Azure Load Testing", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02944-icon-service-Azure-Load-Testing.svg" + }, + { + "id": "azure:azure-local", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Local", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/033745116-icon-service-Azure-Local.svg" + }, + { + "id": "azure:azure-machine-learning", + "subject": "ai + machine learning product or service", + "productName": "Azure Machine Learning", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470510-icon-service-Azure-Machine-Learning.svg" + }, + { + "id": "azure:azure-managed-grafana", + "subject": "other product or service", + "productName": "Azure Managed Grafana", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02905-icon-service-Azure-Managed-Grafana.svg" + }, + { + "id": "azure:azure-managed-redis", + "subject": "databases product or service", + "productName": "Azure Managed Redis", + "recommendedNodeKind": "cache", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/03675-icon-service-Azure-Managed-Redis.svg" + }, + { + "id": "azure:azure-maps-accounts", + "subject": "iot product or service", + "productName": "Azure Maps Accounts", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10185-icon-service-Azure-Maps-Accounts.svg" + }, + { + "id": "azure:azure-media-service", + "subject": "web product or service", + "productName": "Azure Media Service", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/10309-icon-service-Azure-Media-Service.svg" + }, + { + "id": "azure:azure-migrate", + "subject": "migrate product or service", + "productName": "Azure Migrate", + "recommendedNodeKind": "service", + "category": "migrate", + "archivePath": "Azure_Public_Service_Icons/Icons/migrate/10281-icon-service-Azure-Migrate.svg" + }, + { + "id": "azure:azure-monitor-dashboard", + "subject": "other product or service", + "productName": "Azure Monitor Dashboard", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02488-icon-service-Azure-Monitor-Dashboard.svg" + }, + { + "id": "azure:azure-monitor-pipeline", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Monitor Pipeline", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03585-icon-service-Azure-Monitor-Pipeline.svg" + }, + { + "id": "azure:azure-monitors-for-sap-solutions", + "subject": "monitor product or service", + "productName": "Azure Monitors for SAP Solutions", + "recommendedNodeKind": "service", + "category": "monitor", + "archivePath": "Azure_Public_Service_Icons/Icons/monitor/00438-icon-service-Azure-Monitors-for-SAP-Solutions.svg" + }, + { + "id": "azure:azure-netapp-files", + "subject": "storage product or service", + "productName": "Azure NetApp Files", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10096-icon-service-Azure-NetApp-Files.svg" + }, + { + "id": "azure:azure-network-function-manager", + "subject": "other product or service", + "productName": "Azure Network Function Manager", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02740-icon-service-Azure-Network-Function-Manager.svg" + }, + { + "id": "azure:azure-network-function-manager-functions", + "subject": "other product or service", + "productName": "Azure Network Function Manager Functions", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01001-icon-service-Azure-Network-Function-Manager-Functions.svg" + }, + { + "id": "azure:azure-object-understanding", + "subject": "ai + machine learning product or service", + "productName": "Azure Object Understanding", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/01688-icon-service-Azure-Object-Understanding.svg" + }, + { + "id": "azure:azure-openai", + "subject": "ai + machine learning product or service", + "productName": "Azure OpenAI", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03438-icon-service-Azure-OpenAI.svg" + }, + { + "id": "azure:azure-operator-5g-core", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Operator 5G Core", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03248-icon-service-Azure-Operator-5G-Core.svg" + }, + { + "id": "azure:azure-operator-insights", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Operator Insights", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03333-icon-service-Azure-Operator-Insights.svg" + }, + { + "id": "azure:azure-operator-nexus", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Operator Nexus", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03324-icon-service-Azure-Operator-Nexus.svg" + }, + { + "id": "azure:azure-operator-service-manager", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Operator Service Manager", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03334-icon-service-Azure-Operator-Service-Manager.svg" + }, + { + "id": "azure:azure-orbital", + "subject": "other product or service", + "productName": "Azure Orbital", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02697-icon-service-Azure-Orbital.svg" + }, + { + "id": "azure:azure-programmable-connectivity", + "subject": "hybrid + multicloud product or service", + "productName": "Azure Programmable Connectivity", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03347-icon-service-Azure-Programmable-Connectivity.svg" + }, + { + "id": "azure:azure-quotas", + "subject": "other product or service", + "productName": "Azure Quotas", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02951-icon-service-Azure-Quotas.svg" + }, + { + "id": "azure:azure-red-hat-openshift", + "subject": "containers product or service", + "productName": "Azure Red Hat OpenShift", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/03331-icon-service-Azure-Red-Hat-OpenShift.svg" + }, + { + "id": "azure:azure-sentinel", + "subject": "security product or service", + "productName": "Azure Sentinel", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10248-icon-service-Azure-Sentinel.svg" + }, + { + "id": "azure:azure-service-bus", + "subject": "integration product or service", + "productName": "Azure Service Bus", + "recommendedNodeKind": "queue", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10836-icon-service-Azure-Service-Bus.svg" + }, + { + "id": "azure:azure-sphere", + "subject": "other product or service", + "productName": "Azure Sphere", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10190-icon-service-Azure-Sphere.svg" + }, + { + "id": "azure:azure-spring-apps", + "subject": "compute product or service", + "productName": "Azure Spring Apps", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10370-icon-service-Azure-Spring-Apps.svg" + }, + { + "id": "azure:azure-sql", + "subject": "databases product or service", + "productName": "Azure SQL", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/02390-icon-service-Azure-SQL.svg" + }, + { + "id": "azure:azure-sql-database", + "subject": "databases product or service", + "productName": "Azure SQL Database", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10130-icon-service-SQL-Database.svg" + }, + { + "id": "azure:azure-sql-edge", + "subject": "databases product or service", + "productName": "Azure SQL Edge", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/02750-icon-service-Azure-SQL-Edge.svg" + }, + { + "id": "azure:azure-sql-server-stretch-databases", + "subject": "databases product or service", + "productName": "Azure SQL Server Stretch Databases", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10137-icon-service-Azure-SQL-Server-Stretch-Databases.svg" + }, + { + "id": "azure:azure-sql-vm", + "subject": "databases product or service", + "productName": "Azure SQL VM", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10124-icon-service-Azure-SQL-VM.svg" + }, + { + "id": "azure:azure-stack-hci-sizer", + "subject": "iot product or service", + "productName": "Azure Stack HCI Sizer", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/03293-icon-service-Azure-Stack-HCI-Sizer.svg" + }, + { + "id": "azure:azure-storage-mover", + "subject": "other product or service", + "productName": "Azure Storage Mover", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03091-icon-service-Azure-Storage-Mover.svg" + }, + { + "id": "azure:azure-support-center-blue", + "subject": "other product or service", + "productName": "Azure Support Center Blue", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02507-icon-service-Azure-Support-Center-Blue.svg" + }, + { + "id": "azure:azure-sustainability", + "subject": "other product or service", + "productName": "Azure Sustainability", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03314-icon-service-Azure-Sustainability.svg" + }, + { + "id": "azure:azure-synapse-analytics", + "subject": "analytics product or service", + "productName": "Azure Synapse Analytics", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/00606-icon-service-Azure-Synapse-Analytics.svg" + }, + { + "id": "azure:azure-token-service", + "subject": "blockchain product or service", + "productName": "Azure Token Service", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10367-icon-service-Azure-Token-Service.svg" + }, + { + "id": "azure:azure-video-indexer", + "subject": "other product or service", + "productName": "Azure Video Indexer", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01800-icon-service-Azure-Video-Indexer.svg" + }, + { + "id": "azure:azure-virtual-desktop", + "subject": "other product or service", + "productName": "Azure Virtual Desktop", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00327-icon-service-Azure-Virtual-Desktop.svg" + }, + { + "id": "azure:azure-vmware-solution", + "subject": "other product or service", + "productName": "Azure VMware Solution", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01219-icon-service-Azure-VMware-Solution.svg" + }, + { + "id": "azure:azure-workbooks", + "subject": "analytics product or service", + "productName": "Azure Workbooks", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/02189-icon-service-Azure-Workbooks.svg" + }, + { + "id": "azure:azureattestation", + "subject": "other product or service", + "productName": "AzureAttestation", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10422-icon-service-AzureAttestation.svg" + }, + { + "id": "azure:azurite", + "subject": "other product or service", + "productName": "Azurite", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02842-icon-service-Azurite.svg" + }, + { + "id": "azure:backlog", + "subject": "general product or service", + "productName": "Backlog", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10853-icon-service-Backlog.svg" + }, + { + "id": "azure:backup-vault", + "subject": "other product or service", + "productName": "Backup Vault", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02361-icon-service-Backup-Vault.svg" + }, + { + "id": "azure:bare-metal-infrastructure", + "subject": "other product or service", + "productName": "Bare Metal Infrastructure", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02561-icon-service-Bare-Metal-Infrastructure.svg" + }, + { + "id": "azure:bastions", + "subject": "networking product or service", + "productName": "Bastions", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02422-icon-service-Bastions.svg" + }, + { + "id": "azure:batch-accounts", + "subject": "compute product or service", + "productName": "Batch Accounts", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10031-icon-service-Batch-Accounts.svg" + }, + { + "id": "azure:batch-ai", + "subject": "ai + machine learning product or service", + "productName": "Batch AI", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00028-icon-service-Batch-AI.svg" + }, + { + "id": "azure:biz-talk", + "subject": "general product or service", + "productName": "Biz Talk", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10779-icon-service-Biz-Talk.svg" + }, + { + "id": "azure:blob-block", + "subject": "general product or service", + "productName": "Blob Block", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10780-icon-service-Blob-Block.svg" + }, + { + "id": "azure:blob-page", + "subject": "general product or service", + "productName": "Blob Page", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10781-icon-service-Blob-Page.svg" + }, + { + "id": "azure:blockchain-applications", + "subject": "blockchain product or service", + "productName": "Blockchain Applications", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10210-icon-service-Blockchain-Applications.svg" + }, + { + "id": "azure:blueprints", + "subject": "management + governance product or service", + "productName": "Blueprints", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00006-icon-service-Blueprints.svg" + }, + { + "id": "azure:bonsai", + "subject": "ai + machine learning product or service", + "productName": "Bonsai", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03337-icon-service-Bonsai.svg" + }, + { + "id": "azure:bot-services", + "subject": "ai + machine learning product or service", + "productName": "Bot Services", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10165-icon-service-Bot-Services.svg" + }, + { + "id": "azure:branch", + "subject": "general product or service", + "productName": "Branch", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10782-icon-service-Branch.svg" + }, + { + "id": "azure:breeze", + "subject": "other product or service", + "productName": "Breeze", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03633-icon-service-Breeze.svg" + }, + { + "id": "azure:browser", + "subject": "general product or service", + "productName": "Browser", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10783-icon-service-Browser.svg" + }, + { + "id": "azure:bug", + "subject": "general product or service", + "productName": "Bug", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10784-icon-service-Bug.svg" + }, + { + "id": "azure:builds", + "subject": "general product or service", + "productName": "Builds", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10785-icon-service-Builds.svg" + }, + { + "id": "azure:business-process-tracking", + "subject": "integration product or service", + "productName": "Business Process Tracking", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/03637-icon-service-Business-Process-Tracking.svg" + }, + { + "id": "azure:cache", + "subject": "general product or service", + "productName": "Cache", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10786-icon-service-Cache.svg" + }, + { + "id": "azure:cache-redis", + "subject": "databases product or service", + "productName": "Cache Redis", + "recommendedNodeKind": "cache", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10137-icon-service-Cache-Redis.svg" + }, + { + "id": "azure:capacity-reservation-groups", + "subject": "other product or service", + "productName": "Capacity Reservation Groups", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02732-icon-service-Capacity-Reservation-Groups.svg" + }, + { + "id": "azure:cdn-profiles", + "subject": "app services product or service", + "productName": "CDN Profiles", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/00056-icon-service-CDN-Profiles.svg" + }, + { + "id": "azure:central-service-instance-for-sap", + "subject": "other product or service", + "productName": "Central Service Instance For SAP", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03092-icon-service-Central-Service-Instance-For-SAP.svg" + }, + { + "id": "azure:ceres", + "subject": "other product or service", + "productName": "Ceres", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02828-icon-service-Ceres.svg" + }, + { + "id": "azure:change-analysis", + "subject": "devops product or service", + "productName": "Change Analysis", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/00563-icon-service-Change-Analysis.svg" + }, + { + "id": "azure:client-apps", + "subject": "intune product or service", + "productName": "Client Apps", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10331-icon-service-Client-Apps.svg" + }, + { + "id": "azure:cloud-services-classic", + "subject": "compute product or service", + "productName": "Cloud Services (Classic)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10030-icon-service-Cloud-Services-(Classic).svg" + }, + { + "id": "azure:cloud-services-extended-support", + "subject": "other product or service", + "productName": "Cloud Services (extended support)", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02505-icon-service-Cloud-Services-(extended-support).svg" + }, + { + "id": "azure:cloudtest", + "subject": "devops product or service", + "productName": "CloudTest", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/02373-icon-service-CloudTest.svg" + }, + { + "id": "azure:code", + "subject": "general product or service", + "productName": "Code", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10787-icon-service-Code.svg" + }, + { + "id": "azure:code-optimization", + "subject": "devops product or service", + "productName": "Code Optimization", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/03455-icon-service-Code-Optimization.svg" + }, + { + "id": "azure:cognitive-search", + "subject": "ai + machine learning product or service", + "productName": "Cognitive Search", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10044-icon-service-Cognitive-Search.svg" + }, + { + "id": "azure:cognitive-services", + "subject": "ai + machine learning product or service", + "productName": "Cognitive Services", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10162-icon-service-Cognitive-Services.svg" + }, + { + "id": "azure:cognitive-services-decisions", + "subject": "ai + machine learning product or service", + "productName": "Cognitive Services Decisions", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03173-icon-service-Cognitive-Services-Decisions.svg" + }, + { + "id": "azure:collaborative-service", + "subject": "azure ecosystem product or service", + "productName": "Collaborative Service", + "recommendedNodeKind": "service", + "category": "azure ecosystem", + "archivePath": "Azure_Public_Service_Icons/Icons/azure ecosystem/01038-icon-service-Collaborative-Service.svg" + }, + { + "id": "azure:commit", + "subject": "general product or service", + "productName": "Commit", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10788-icon-service-Commit.svg" + }, + { + "id": "azure:community-images", + "subject": "other product or service", + "productName": "Community Images", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02865-icon-service-Community-Images.svg" + }, + { + "id": "azure:compliance", + "subject": "management + governance product or service", + "productName": "Compliance", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00011-icon-service-Compliance.svg" + }, + { + "id": "azure:compliance-center", + "subject": "other product or service", + "productName": "Compliance Center", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02931-icon-service-Compliance-Center.svg" + }, + { + "id": "azure:compute-fleet", + "subject": "compute product or service", + "productName": "Compute Fleet", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/03487-icon-service-Compute-Fleet.svg" + }, + { + "id": "azure:computer-vision", + "subject": "ai + machine learning product or service", + "productName": "Computer Vision", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00792-icon-service-Computer-Vision.svg" + }, + { + "id": "azure:conditional-access", + "subject": "security product or service", + "productName": "Conditional Access", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10233-icon-service-Conditional-Access.svg" + }, + { + "id": "azure:confidential-ledgers", + "subject": "other product or service", + "productName": "Confidential Ledgers", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02668-icon-service-Confidential-Ledgers.svg" + }, + { + "id": "azure:connected-cache", + "subject": "networking product or service", + "productName": "Connected Cache", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02509-icon-service-Connected-Cache.svg" + }, + { + "id": "azure:connected-vehicle-platform", + "subject": "other product or service", + "productName": "Connected Vehicle Platform", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02573-icon-service-Connected-Vehicle-Platform.svg" + }, + { + "id": "azure:connections", + "subject": "networking product or service", + "productName": "Connections", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10081-icon-service-Connections.svg" + }, + { + "id": "azure:consortium", + "subject": "blockchain product or service", + "productName": "Consortium", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10375-icon-service-Consortium.svg" + }, + { + "id": "azure:container-apps-environments", + "subject": "other product or service", + "productName": "Container Apps Environments", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02989-icon-service-Container-Apps-Environments.svg" + }, + { + "id": "azure:container-instances", + "subject": "compute product or service", + "productName": "Container Instances", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10104-icon-service-Container-Instances.svg" + }, + { + "id": "azure:container-registries", + "subject": "containers product or service", + "productName": "Container Registries", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/10105-icon-service-Container-Registries.svg" + }, + { + "id": "azure:container-services-deprecated", + "subject": "compute product or service", + "productName": "Container Services (Deprecated)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10049-icon-service-Container-Services-(Deprecated).svg" + }, + { + "id": "azure:content-moderators", + "subject": "ai + machine learning product or service", + "productName": "Content Moderators", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00795-icon-service-Content-Moderators.svg" + }, + { + "id": "azure:content-safety", + "subject": "ai + machine learning product or service", + "productName": "Content Safety", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03390-icon-service-Content-Safety.svg" + }, + { + "id": "azure:controls", + "subject": "general product or service", + "productName": "Controls", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10789-icon-service-Controls.svg" + }, + { + "id": "azure:controls-horizontal", + "subject": "general product or service", + "productName": "Controls Horizontal", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10790-icon-service-Controls-Horizontal.svg" + }, + { + "id": "azure:cost-alerts", + "subject": "general product or service", + "productName": "Cost Alerts", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10791-icon-service-Cost-Alerts.svg" + }, + { + "id": "azure:cost-analysis", + "subject": "general product or service", + "productName": "Cost Analysis", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10792-icon-service-Cost-Analysis.svg" + }, + { + "id": "azure:cost-budgets", + "subject": "general product or service", + "productName": "Cost Budgets", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10793-icon-service-Cost-Budgets.svg" + }, + { + "id": "azure:cost-export", + "subject": "other product or service", + "productName": "Cost Export", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00913-icon-service-Cost-Export.svg" + }, + { + "id": "azure:cost-management", + "subject": "general product or service", + "productName": "Cost Management", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10019-icon-service-Cost-Management.svg" + }, + { + "id": "azure:cost-management-and-billing", + "subject": "general product or service", + "productName": "Cost Management and Billing", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/00004-icon-service-Cost-Management-and-Billing.svg" + }, + { + "id": "azure:counter", + "subject": "general product or service", + "productName": "Counter", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10794-icon-service-Counter.svg" + }, + { + "id": "azure:cubes", + "subject": "general product or service", + "productName": "Cubes", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10795-icon-service-Cubes.svg" + }, + { + "id": "azure:custom-ip-prefix", + "subject": "other product or service", + "productName": "Custom IP Prefix", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02654-icon-service-Custom-IP-Prefix.svg" + }, + { + "id": "azure:custom-vision", + "subject": "ai + machine learning product or service", + "productName": "Custom Vision", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00793-icon-service-Custom-Vision.svg" + }, + { + "id": "azure:customer-lockbox-for-microsoft-azure", + "subject": "management + governance product or service", + "productName": "Customer Lockbox for Microsoft Azure", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10314-icon-service-Customer-Lockbox-for-Microsoft-Azure.svg" + }, + { + "id": "azure:dashboard", + "subject": "general product or service", + "productName": "Dashboard", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10015-icon-service-Dashboard.svg" + }, + { + "id": "azure:dashboard-hub", + "subject": "other product or service", + "productName": "Dashboard Hub", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01757-icon-service-Dashboard-Hub.svg" + }, + { + "id": "azure:data-box", + "subject": "migrate product or service", + "productName": "Data Box", + "recommendedNodeKind": "service", + "category": "migrate", + "archivePath": "Azure_Public_Service_Icons/Icons/migrate/10094-icon-service-Data-Box.svg" + }, + { + "id": "azure:data-collection-rules", + "subject": "other product or service", + "productName": "Data Collection Rules", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01857-icon-service-Data-Collection-Rules.svg" + }, + { + "id": "azure:data-factories", + "subject": "analytics product or service", + "productName": "Data Factories", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10126-icon-service-Data-Factories.svg" + }, + { + "id": "azure:data-lake-analytics", + "subject": "analytics product or service", + "productName": "Data Lake Analytics", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10143-icon-service-Data-Lake-Analytics.svg" + }, + { + "id": "azure:data-lake-storage-gen1", + "subject": "storage product or service", + "productName": "Data Lake Storage Gen1", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10090-icon-service-Data-Lake-Storage-Gen1.svg" + }, + { + "id": "azure:data-lake-store-gen1", + "subject": "analytics product or service", + "productName": "Data Lake Store Gen1", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10150-icon-service-Data-Lake-Store-Gen1.svg" + }, + { + "id": "azure:data-share-invitations", + "subject": "storage product or service", + "productName": "Data Share Invitations", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10097-icon-service-Data-Share-Invitations.svg" + }, + { + "id": "azure:data-shares", + "subject": "storage product or service", + "productName": "Data Shares", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10098-icon-service-Data-Shares.svg" + }, + { + "id": "azure:data-virtualization", + "subject": "storage product or service", + "productName": "Data Virtualization", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/029203566-icon-service-Data-Virtualization.svg" + }, + { + "id": "azure:database-instance-for-sap", + "subject": "other product or service", + "productName": "Database Instance For SAP", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03175-icon-service-Database-Instance-For-SAP.svg" + }, + { + "id": "azure:ddos-custom-policy", + "subject": "new icons product or service", + "productName": "DDoS Custom Policy", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/035556610-icon-service-DDoS-Custom-Policy.svg" + }, + { + "id": "azure:ddos-protection-plans", + "subject": "networking product or service", + "productName": "DDoS Protection Plans", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10072-icon-service-DDoS-Protection-Plans.svg" + }, + { + "id": "azure:dedicated-hsm", + "subject": "other product or service", + "productName": "Dedicated HSM", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02322-icon-service-Dedicated-HSM.svg" + }, + { + "id": "azure:defender-cm-local-manager", + "subject": "other product or service", + "productName": "Defender CM Local Manager", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03402-icon-service-Defender-CM-Local-Manager.svg" + }, + { + "id": "azure:defender-dcs-controller", + "subject": "other product or service", + "productName": "Defender DCS Controller", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03412-icon-service-Defender-DCS-Controller.svg" + }, + { + "id": "azure:defender-distributer-control-system", + "subject": "other product or service", + "productName": "Defender Distributer Control System", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03413-icon-service-Defender-Distributer-Control-System.svg" + }, + { + "id": "azure:defender-engineering-station", + "subject": "other product or service", + "productName": "Defender Engineering Station", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03414-icon-service-Defender-Engineering-Station.svg" + }, + { + "id": "azure:defender-external-management", + "subject": "other product or service", + "productName": "Defender External Management", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03403-icon-service-Defender-External-Management.svg" + }, + { + "id": "azure:defender-freezer-monitor", + "subject": "other product or service", + "productName": "Defender Freezer Monitor", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03404-icon-service-Defender-Freezer-Monitor.svg" + }, + { + "id": "azure:defender-historian", + "subject": "other product or service", + "productName": "Defender Historian", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03405-icon-service-Defender-Historian.svg" + }, + { + "id": "azure:defender-hmi", + "subject": "other product or service", + "productName": "Defender HMI", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03406-icon-service-Defender-HMI.svg" + }, + { + "id": "azure:defender-industrial-packaging-system", + "subject": "other product or service", + "productName": "Defender Industrial Packaging System", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03415-icon-service-Defender-Industrial-Packaging-System.svg" + }, + { + "id": "azure:defender-industrial-printer", + "subject": "other product or service", + "productName": "Defender Industrial Printer", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03416-icon-service-Defender-Industrial-Printer.svg" + }, + { + "id": "azure:defender-industrial-robot", + "subject": "other product or service", + "productName": "Defender Industrial Robot", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03418-icon-service-Defender-Industrial-Robot.svg" + }, + { + "id": "azure:defender-industrial-scale-system", + "subject": "other product or service", + "productName": "Defender Industrial Scale System", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03417-icon-service-Defender-Industrial-Scale-System.svg" + }, + { + "id": "azure:defender-marquee", + "subject": "other product or service", + "productName": "Defender Marquee", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03407-icon-service-Defender-Marquee.svg" + }, + { + "id": "azure:defender-meter", + "subject": "other product or service", + "productName": "Defender Meter", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03419-icon-service-Defender-Meter.svg" + }, + { + "id": "azure:defender-plc", + "subject": "other product or service", + "productName": "Defender PLC", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03420-icon-service-Defender-PLC.svg" + }, + { + "id": "azure:defender-pneumatic-device", + "subject": "other product or service", + "productName": "Defender Pneumatic Device", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03421-icon-service-Defender-Pneumatic-Device.svg" + }, + { + "id": "azure:defender-programable-board", + "subject": "other product or service", + "productName": "Defender Programable Board", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03422-icon-service-Defender-Programable-Board.svg" + }, + { + "id": "azure:defender-relay", + "subject": "other product or service", + "productName": "Defender Relay", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03423-icon-service-Defender-Relay.svg" + }, + { + "id": "azure:defender-robot-controller", + "subject": "other product or service", + "productName": "Defender Robot Controller", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03408-icon-service-Defender-Robot-Controller.svg" + }, + { + "id": "azure:defender-rtu", + "subject": "other product or service", + "productName": "Defender RTU", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03424-icon-service-Defender-RTU.svg" + }, + { + "id": "azure:defender-sensor", + "subject": "other product or service", + "productName": "Defender Sensor", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03409-icon-service-Defender-Sensor.svg" + }, + { + "id": "azure:defender-slot", + "subject": "other product or service", + "productName": "Defender Slot", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03410-icon-service-Defender-Slot.svg" + }, + { + "id": "azure:defender-web-guiding-system", + "subject": "other product or service", + "productName": "Defender Web Guiding System", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03411-icon-service-Defender-Web-Guiding-System.svg" + }, + { + "id": "azure:detonation", + "subject": "security product or service", + "productName": "Detonation", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/00378-icon-service-Detonation.svg" + }, + { + "id": "azure:dev-console", + "subject": "general product or service", + "productName": "Dev Console", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10796-icon-service-Dev-Console.svg" + }, + { + "id": "azure:device-compliance", + "subject": "intune product or service", + "productName": "Device Compliance", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10333-icon-service-Device-Compliance.svg" + }, + { + "id": "azure:device-configuration", + "subject": "intune product or service", + "productName": "Device Configuration", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10338-icon-service-Device-Configuration.svg" + }, + { + "id": "azure:device-enrollment", + "subject": "intune product or service", + "productName": "Device Enrollment", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10337-icon-service-Device-Enrollment.svg" + }, + { + "id": "azure:device-provisioning-services", + "subject": "iot product or service", + "productName": "Device Provisioning Services", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10369-icon-service-Device-Provisioning-Services.svg" + }, + { + "id": "azure:device-security-apple", + "subject": "intune product or service", + "productName": "Device Security Apple", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/00399-icon-service-Device-Security-Apple.svg" + }, + { + "id": "azure:device-security-google", + "subject": "intune product or service", + "productName": "Device Security Google", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/00399-icon-service-Device-Security-Google.svg" + }, + { + "id": "azure:device-security-windows", + "subject": "intune product or service", + "productName": "Device Security Windows", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/00399-icon-service-Device-Security-Windows.svg" + }, + { + "id": "azure:device-update-iot-hub", + "subject": "other product or service", + "productName": "Device Update IoT Hub", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02475-icon-service-Device-Update-IoT-Hub.svg" + }, + { + "id": "azure:devices", + "subject": "intune product or service", + "productName": "Devices", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10332-icon-service-Devices.svg" + }, + { + "id": "azure:devops-starter", + "subject": "devops product or service", + "productName": "DevOps Starter", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/03339-icon-service-DevOps-Starter.svg" + }, + { + "id": "azure:devtest-labs", + "subject": "devops product or service", + "productName": "DevTest Labs", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/10264-icon-service-DevTest-Labs.svg" + }, + { + "id": "azure:diagnostics-settings", + "subject": "management + governance product or service", + "productName": "Diagnostics Settings", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00008-icon-service-Diagnostics-Settings.svg" + }, + { + "id": "azure:digital-twins", + "subject": "iot product or service", + "productName": "Digital Twins", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/01030-icon-service-Digital-Twins.svg" + }, + { + "id": "azure:disconnected-operations", + "subject": "new icons product or service", + "productName": "Disconnected Operations", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/035712231-icon-service-Disconnected-Operations.svg" + }, + { + "id": "azure:disk-encryption-sets", + "subject": "compute product or service", + "productName": "Disk Encryption Sets", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00398-icon-service-Disk-Encryption-Sets.svg" + }, + { + "id": "azure:disk-pool", + "subject": "other product or service", + "productName": "Disk Pool", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02560-icon-service-Disk-Pool.svg" + }, + { + "id": "azure:disks", + "subject": "compute product or service", + "productName": "Disks", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10032-icon-service-Disks.svg" + }, + { + "id": "azure:disks-classic", + "subject": "compute product or service", + "productName": "Disks (Classic)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10041-icon-service-Disks-(Classic).svg" + }, + { + "id": "azure:disks-snapshots", + "subject": "compute product or service", + "productName": "Disks Snapshots", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10026-icon-service-Disks-Snapshots.svg" + }, + { + "id": "azure:dns-multistack", + "subject": "networking product or service", + "productName": "DNS Multistack", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03459-icon-service-DNS-Multistack.svg" + }, + { + "id": "azure:dns-private-resolver", + "subject": "networking product or service", + "productName": "DNS Private Resolver", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02882-icon-service-DNS-Private-Resolver.svg" + }, + { + "id": "azure:dns-security-policy", + "subject": "networking product or service", + "productName": "DNS Security Policy", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03368-icon-service-DNS-Security-Policy.svg" + }, + { + "id": "azure:dns-zones", + "subject": "networking product or service", + "productName": "DNS Zones", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10064-icon-service-DNS-Zones.svg" + }, + { + "id": "azure:download", + "subject": "general product or service", + "productName": "Download", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10797-icon-service-Download.svg" + }, + { + "id": "azure:ebooks", + "subject": "intune product or service", + "productName": "eBooks", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10330-icon-service-eBooks.svg" + }, + { + "id": "azure:edge-actions", + "subject": "networking product or service", + "productName": "Edge Actions", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/029273094-icon-service-Edge-Actions.svg" + }, + { + "id": "azure:edge-management", + "subject": "other product or service", + "productName": "Edge Management", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10117-icon-service-Edge-Management.svg" + }, + { + "id": "azure:edge-storage-accelerator", + "subject": "hybrid + multicloud product or service", + "productName": "Edge Storage Accelerator", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/03521-icon-service-Edge-Storage-Accelerator.svg" + }, + { + "id": "azure:education", + "subject": "management + governance product or service", + "productName": "Education", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00026-icon-service-Education.svg" + }, + { + "id": "azure:elastic-job-agents", + "subject": "databases product or service", + "productName": "Elastic Job Agents", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10128-icon-service-Elastic-Job-Agents.svg" + }, + { + "id": "azure:elastic-san", + "subject": "other product or service", + "productName": "Elastic SAN", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03190-icon-service-Elastic-SAN.svg" + }, + { + "id": "azure:endpoint-analytics", + "subject": "analytics product or service", + "productName": "Endpoint Analytics", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/00562-icon-service-Endpoint-Analytics.svg" + }, + { + "id": "azure:engage-center-connect", + "subject": "intune product or service", + "productName": "Engage Center Connect", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/029797391-icon-service-Engage-Center-Connect.svg" + }, + { + "id": "azure:enterprise-applications", + "subject": "identity product or service", + "productName": "Enterprise Applications", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10225-icon-service-Enterprise-Applications.svg" + }, + { + "id": "azure:entra-connect", + "subject": "identity product or service", + "productName": "Entra Connect", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02854-icon-service-Entra-Connect.svg" + }, + { + "id": "azure:entra-connect-health", + "subject": "identity product or service", + "productName": "Entra Connect Health", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10224-icon-service-Entra-Connect-Health.svg" + }, + { + "id": "azure:entra-connect-sync", + "subject": "identity product or service", + "productName": "Entra Connect Sync", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03533-icon-service-Entra-Connect-Sync.svg" + }, + { + "id": "azure:entra-domain-services", + "subject": "identity product or service", + "productName": "Entra Domain Services", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10222-icon-service-Entra-Domain-Services.svg" + }, + { + "id": "azure:entra-global-secure-access", + "subject": "identity product or service", + "productName": "Entra Global Secure Access", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03309-icon-service-Entra-Global-Secure-Access.svg" + }, + { + "id": "azure:entra-id-protection", + "subject": "identity product or service", + "productName": "Entra ID Protection", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10231-icon-service-Entra-ID-Protection.svg" + }, + { + "id": "azure:entra-identity-custom-roles", + "subject": "identity product or service", + "productName": "Entra Identity Custom Roles", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02680-icon-service-Entra-Identity-Custom-Roles.svg" + }, + { + "id": "azure:entra-identity-licenses", + "subject": "identity product or service", + "productName": "Entra Identity Licenses", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02681-icon-service-Entra-Identity-Licenses.svg" + }, + { + "id": "azure:entra-identity-risky-signins", + "subject": "security product or service", + "productName": "Entra Identity Risky Signins", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/03341-icon-service-Entra-Identity-Risky-Signins.svg" + }, + { + "id": "azure:entra-identity-risky-users", + "subject": "security product or service", + "productName": "Entra Identity Risky Users", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/03342-icon-service-Entra-Identity-Risky-Users.svg" + }, + { + "id": "azure:entra-identity-roles-and-administrators", + "subject": "identity product or service", + "productName": "Entra Identity Roles and Administrators", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10340-icon-service-Entra-Identity-Roles-and-Administrators.svg" + }, + { + "id": "azure:entra-internet-access", + "subject": "identity product or service", + "productName": "Entra Internet Access", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03383-icon-service-Entra-Internet-Access.svg" + }, + { + "id": "azure:entra-managed-identities", + "subject": "identity product or service", + "productName": "Entra Managed Identities", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10227-icon-service-Entra-Managed-Identities.svg" + }, + { + "id": "azure:entra-private-access", + "subject": "identity product or service", + "productName": "Entra Private Access", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03382-icon-service-Entra-Private-Access.svg" + }, + { + "id": "azure:entra-privleged-identity-management", + "subject": "identity product or service", + "productName": "Entra Privleged Identity Management", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02251-icon-service-Entra-Privleged-Identity-Management.svg" + }, + { + "id": "azure:entra-verified-id", + "subject": "identity product or service", + "productName": "Entra Verified ID", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03143-icon-service-Entra-Verified-ID.svg" + }, + { + "id": "azure:error", + "subject": "general product or service", + "productName": "Error", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10798-icon-service-Error.svg" + }, + { + "id": "azure:event-grid-domains", + "subject": "integration product or service", + "productName": "Event Grid Domains", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10215-icon-service-Event-Grid-Domains.svg" + }, + { + "id": "azure:event-grid-subscriptions", + "subject": "integration product or service", + "productName": "Event Grid Subscriptions", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10221-icon-service-Event-Grid-Subscriptions.svg" + }, + { + "id": "azure:event-grid-topics", + "subject": "integration product or service", + "productName": "Event Grid Topics", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10206-icon-service-Event-Grid-Topics.svg" + }, + { + "id": "azure:event-hub-clusters", + "subject": "analytics product or service", + "productName": "Event Hub Clusters", + "recommendedNodeKind": "queue", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10149-icon-service-Event-Hub-Clusters.svg" + }, + { + "id": "azure:event-hubs", + "subject": "analytics product or service", + "productName": "Event Hubs", + "recommendedNodeKind": "queue", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/00039-icon-service-Event-Hubs.svg" + }, + { + "id": "azure:exchange-access", + "subject": "intune product or service", + "productName": "Exchange Access", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10339-icon-service-Exchange-Access.svg" + }, + { + "id": "azure:exchange-on-premises-access", + "subject": "other product or service", + "productName": "Exchange On Premises Access", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10334-icon-service-Exchange-On-Premises-Access.svg" + }, + { + "id": "azure:express-route-traffic-collector", + "subject": "other product or service", + "productName": "Express Route Traffic Collector", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03137-icon-service-Express-Route-Traffic-Collector.svg" + }, + { + "id": "azure:expressroute-circuits", + "subject": "networking product or service", + "productName": "ExpressRoute Circuits", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10079-icon-service-ExpressRoute-Circuits.svg" + }, + { + "id": "azure:expressroute-direct", + "subject": "other product or service", + "productName": "ExpressRoute Direct", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00903-icon-service-ExpressRoute-Direct.svg" + }, + { + "id": "azure:extendedsecurityupdates", + "subject": "security product or service", + "productName": "ExtendedSecurityUpdates", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10572-icon-service-ExtendedSecurityUpdates.svg" + }, + { + "id": "azure:extensions", + "subject": "general product or service", + "productName": "Extensions", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10799-icon-service-Extensions.svg" + }, + { + "id": "azure:external-id", + "subject": "identity product or service", + "productName": "external id", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03425-icon-service-external-id.svg" + }, + { + "id": "azure:external-id-modified", + "subject": "identity product or service", + "productName": "external id modified", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/034251-icon-service-external-id-modified.svg" + }, + { + "id": "azure:external-identities", + "subject": "identity product or service", + "productName": "External Identities", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03338-icon-service-External-Identities.svg" + }, + { + "id": "azure:face-apis", + "subject": "ai + machine learning product or service", + "productName": "Face APIs", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00794-icon-service-Face-APIs.svg" + }, + { + "id": "azure:feature-previews", + "subject": "general product or service", + "productName": "Feature Previews", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10827-icon-service-Feature-Previews.svg" + }, + { + "id": "azure:fhir-service", + "subject": "other product or service", + "productName": "FHIR Service", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02658-icon-service-FHIR-Service.svg" + }, + { + "id": "azure:fiji", + "subject": "other product or service", + "productName": "Fiji", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02486-icon-service-Fiji.svg" + }, + { + "id": "azure:file", + "subject": "general product or service", + "productName": "File", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10800-icon-service-File.svg" + }, + { + "id": "azure:files", + "subject": "general product or service", + "productName": "Files", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10801-icon-service-Files.svg" + }, + { + "id": "azure:firewalls", + "subject": "networking product or service", + "productName": "Firewalls", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10084-icon-service-Firewalls.svg" + }, + { + "id": "azure:folder-blank", + "subject": "general product or service", + "productName": "Folder Blank", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10802-icon-service-Folder-Blank.svg" + }, + { + "id": "azure:folder-website", + "subject": "general product or service", + "productName": "Folder Website", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10803-icon-service-Folder-Website.svg" + }, + { + "id": "azure:form-recognizers", + "subject": "ai + machine learning product or service", + "productName": "Form Recognizers", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00819-icon-service-Form-Recognizers.svg" + }, + { + "id": "azure:foundry-agent-service", + "subject": "ai + machine learning product or service", + "productName": "Foundry Agent Service", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470523-icon-service-Foundry-Agent-Service.svg" + }, + { + "id": "azure:foundry-application", + "subject": "ai + machine learning product or service", + "productName": "Foundry Application", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/036509374-icon-service-Foundry-Application.svg" + }, + { + "id": "azure:foundry-control-plane", + "subject": "ai + machine learning product or service", + "productName": "Foundry Control Plane", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470534-icon-service-Foundry-Control-Plane.svg" + }, + { + "id": "azure:foundry-labs", + "subject": "ai + machine learning product or service", + "productName": "Foundry Labs", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470555-icon-service-Foundry-Labs.svg" + }, + { + "id": "azure:foundry-local", + "subject": "ai + machine learning product or service", + "productName": "Foundry Local", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470593-icon-service-Foundry-Local.svg" + }, + { + "id": "azure:foundry-models", + "subject": "ai + machine learning product or service", + "productName": "Foundry Models", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/038470614-icon-service-Foundry-Models.svg" + }, + { + "id": "azure:foundry-project", + "subject": "ai + machine learning product or service", + "productName": "Foundry Project", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/036509415-icon-service-Foundry-Project.svg" + }, + { + "id": "azure:frd-qa", + "subject": "ai + machine learning product or service", + "productName": "FRD QA", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/029455661-icon-service-FRD-QA.svg" + }, + { + "id": "azure:free-services", + "subject": "general product or service", + "productName": "Free Services", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10016-icon-service-Free-Services.svg" + }, + { + "id": "azure:front-door-and-cdn-profiles", + "subject": "networking product or service", + "productName": "Front Door and CDN Profiles", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10073-icon-service-Front-Door-and-CDN-Profiles.svg" + }, + { + "id": "azure:ftp", + "subject": "general product or service", + "productName": "FTP", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10804-icon-service-FTP.svg" + }, + { + "id": "azure:function-apps", + "subject": "compute product or service", + "productName": "Function Apps", + "recommendedNodeKind": "function", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10029-icon-service-Function-Apps.svg" + }, + { + "id": "azure:gear", + "subject": "general product or service", + "productName": "Gear", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10805-icon-service-Gear.svg" + }, + { + "id": "azure:genomics", + "subject": "ai + machine learning product or service", + "productName": "Genomics", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00031-icon-service-Genomics.svg" + }, + { + "id": "azure:genomics-accounts", + "subject": "ai + machine learning product or service", + "productName": "Genomics Accounts", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10164-icon-service-Genomics-Accounts.svg" + }, + { + "id": "azure:globe-error", + "subject": "general product or service", + "productName": "Globe Error", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10807-icon-service-Globe-Error.svg" + }, + { + "id": "azure:globe-success", + "subject": "general product or service", + "productName": "Globe Success", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10808-icon-service-Globe-Success.svg" + }, + { + "id": "azure:globe-warning", + "subject": "general product or service", + "productName": "Globe Warning", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10809-icon-service-Globe-Warning.svg" + }, + { + "id": "azure:groups", + "subject": "identity product or service", + "productName": "Groups", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10223-icon-service-Groups.svg" + }, + { + "id": "azure:guide", + "subject": "general product or service", + "productName": "Guide", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10810-icon-service-Guide.svg" + }, + { + "id": "azure:hd-insight-clusters", + "subject": "analytics product or service", + "productName": "HD Insight Clusters", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/10142-icon-service-HD-Insight-Clusters.svg" + }, + { + "id": "azure:hdi-aks-cluster", + "subject": "other product or service", + "productName": "HDI AKS Cluster", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03468-icon-service-HDI-AKS-Cluster.svg" + }, + { + "id": "azure:heart", + "subject": "general product or service", + "productName": "Heart", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10811-icon-service-Heart.svg" + }, + { + "id": "azure:help-and-support", + "subject": "general product or service", + "productName": "Help and Support", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10013-icon-service-Help-and-Support.svg" + }, + { + "id": "azure:host-groups", + "subject": "compute product or service", + "productName": "Host Groups", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10346-icon-service-Host-Groups.svg" + }, + { + "id": "azure:host-pools", + "subject": "compute product or service", + "productName": "Host Pools", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00328-icon-service-Host-Pools.svg" + }, + { + "id": "azure:hosts", + "subject": "compute product or service", + "productName": "Hosts", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10347-icon-service-Hosts.svg" + }, + { + "id": "azure:hybrid-connectivity-hub", + "subject": "iot product or service", + "productName": "Hybrid Connectivity Hub", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/03656-icon-service-Hybrid-Connectivity-Hub.svg" + }, + { + "id": "azure:icm-troubleshooting", + "subject": "other product or service", + "productName": "IcM Troubleshooting", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03361-icon-service-IcM-Troubleshooting.svg" + }, + { + "id": "azure:identity-governance", + "subject": "identity product or service", + "productName": "Identity Governance", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10235-icon-service-Identity-Governance.svg" + }, + { + "id": "azure:identity-secure-score", + "subject": "security product or service", + "productName": "Identity Secure Score", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/03340-icon-service-Identity-Secure-Score.svg" + }, + { + "id": "azure:image", + "subject": "general product or service", + "productName": "Image", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10812-icon-service-Image.svg" + }, + { + "id": "azure:image-definitions", + "subject": "compute product or service", + "productName": "Image Definitions", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10037-icon-service-Image-Definitions.svg" + }, + { + "id": "azure:image-templates", + "subject": "compute product or service", + "productName": "Image Templates", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02634-icon-service-Image-Templates.svg" + }, + { + "id": "azure:image-versions", + "subject": "compute product or service", + "productName": "Image Versions", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10038-icon-service-Image-Versions.svg" + }, + { + "id": "azure:images", + "subject": "compute product or service", + "productName": "Images", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10033-icon-service-Images.svg" + }, + { + "id": "azure:immersive-readers", + "subject": "ai + machine learning product or service", + "productName": "Immersive Readers", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00812-icon-service-Immersive-Readers.svg" + }, + { + "id": "azure:import-export-jobs", + "subject": "storage product or service", + "productName": "Import Export Jobs", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10100-icon-service-Import-Export-Jobs.svg" + }, + { + "id": "azure:industrial-iot", + "subject": "iot product or service", + "productName": "Industrial IoT", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/02359-icon-service-Industrial-IoT.svg" + }, + { + "id": "azure:information", + "subject": "general product or service", + "productName": "Information", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10005-icon-service-Information.svg" + }, + { + "id": "azure:input-output", + "subject": "general product or service", + "productName": "Input Output", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10813-icon-service-Input-Output.svg" + }, + { + "id": "azure:instance-pools", + "subject": "databases product or service", + "productName": "Instance Pools", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10139-icon-service-Instance-Pools.svg" + }, + { + "id": "azure:integration-accounts", + "subject": "integration product or service", + "productName": "Integration Accounts", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10218-icon-service-Integration-Accounts.svg" + }, + { + "id": "azure:integration-environments", + "subject": "integration product or service", + "productName": "Integration Environments", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/03345-icon-service-Integration-Environments.svg" + }, + { + "id": "azure:integration-service-environments", + "subject": "integration product or service", + "productName": "Integration Service Environments", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/00555-icon-service-Integration-Service-Environments.svg" + }, + { + "id": "azure:internet-analyzer-profiles", + "subject": "other product or service", + "productName": "Internet Analyzer Profiles", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00469-icon-service-Internet-Analyzer-Profiles.svg" + }, + { + "id": "azure:intune", + "subject": "intune product or service", + "productName": "Intune", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10329-icon-service-Intune.svg" + }, + { + "id": "azure:intune-app-protection", + "subject": "intune product or service", + "productName": "Intune App Protection", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10344-icon-service-Intune-App-Protection.svg" + }, + { + "id": "azure:intune-for-education", + "subject": "intune product or service", + "productName": "Intune For Education", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10343-icon-service-Intune-For-Education.svg" + }, + { + "id": "azure:intune-trends", + "subject": "management + governance product or service", + "productName": "Intune Trends", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00408-icon-service-Intune-Trends.svg" + }, + { + "id": "azure:iot-central-applications", + "subject": "iot product or service", + "productName": "IoT Central Applications", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10184-icon-service-IoT-Central-Applications.svg" + }, + { + "id": "azure:iot-edge", + "subject": "iot product or service", + "productName": "IoT Edge", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10186-icon-service-IoT-Edge.svg" + }, + { + "id": "azure:iot-hub", + "subject": "iot product or service", + "productName": "IoT Hub", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10182-icon-service-IoT-Hub.svg" + }, + { + "id": "azure:ip-address-manager", + "subject": "networking product or service", + "productName": "IP Address manager", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03461-icon-service-IP-Address-manager.svg" + }, + { + "id": "azure:ip-groups", + "subject": "networking product or service", + "productName": "IP Groups", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/00701-icon-service-IP-Groups.svg" + }, + { + "id": "azure:journey-hub", + "subject": "general product or service", + "productName": "Journey Hub", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10814-icon-service-Journey-Hub.svg" + }, + { + "id": "azure:key-vaults", + "subject": "security product or service", + "productName": "Key Vaults", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10245-icon-service-Key-Vaults.svg" + }, + { + "id": "azure:keys", + "subject": "menu product or service", + "productName": "Keys", + "recommendedNodeKind": "service", + "category": "menu", + "archivePath": "Azure_Public_Service_Icons/Icons/menu/00787-icon-service-Keys.svg" + }, + { + "id": "azure:kubernetes-fleet-manager", + "subject": "other product or service", + "productName": "Kubernetes Fleet Manager", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03134-icon-service-Kubernetes-Fleet-Manager.svg" + }, + { + "id": "azure:kubernetes-hub", + "subject": "containers product or service", + "productName": "Kubernetes Hub", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/033545113-icon-service-Kubernetes-Hub.svg" + }, + { + "id": "azure:lab-accounts", + "subject": "devops product or service", + "productName": "Lab Accounts", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/02761-icon-service-Lab-Accounts.svg" + }, + { + "id": "azure:lab-services", + "subject": "devops product or service", + "productName": "Lab Services", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/10265-icon-service-Lab-Services.svg" + }, + { + "id": "azure:landing-zone", + "subject": "new icons product or service", + "productName": "Landing Zone", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/029636048-icon-service-Landing-Zone.svg" + }, + { + "id": "azure:language", + "subject": "ai + machine learning product or service", + "productName": "Language", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/02876-icon-service-Language.svg" + }, + { + "id": "azure:language-understanding", + "subject": "ai + machine learning product or service", + "productName": "Language Understanding", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00801-icon-service-Language-Understanding.svg" + }, + { + "id": "azure:launch-portal", + "subject": "general product or service", + "productName": "Launch Portal", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10815-icon-service-Launch-Portal.svg" + }, + { + "id": "azure:learn", + "subject": "general product or service", + "productName": "Learn", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10816-icon-service-Learn.svg" + }, + { + "id": "azure:load-balancer-hub", + "subject": "networking product or service", + "productName": "Load Balancer Hub", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02302-icon-service-Load-Balancer-Hub.svg" + }, + { + "id": "azure:load-balancer-hub-029029174", + "subject": "networking product or service", + "productName": "Load Balancer Hub", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/029029174-icon-service-Load-Balancer-Hub.svg" + }, + { + "id": "azure:load-balancers", + "subject": "networking product or service", + "productName": "Load Balancers", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10062-icon-service-Load-Balancers.svg" + }, + { + "id": "azure:load-test", + "subject": "general product or service", + "productName": "Load Test", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10817-icon-service-Load-Test.svg" + }, + { + "id": "azure:load-testing", + "subject": "devops product or service", + "productName": "Load Testing", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/02423-icon-service-Load-Testing.svg" + }, + { + "id": "azure:local-network-gateways", + "subject": "networking product or service", + "productName": "Local Network Gateways", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10077-icon-service-Local-Network-Gateways.svg" + }, + { + "id": "azure:location", + "subject": "general product or service", + "productName": "Location", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10818-icon-service-Location.svg" + }, + { + "id": "azure:log-analytics-query-pack", + "subject": "other product or service", + "productName": "Log Analytics Query Pack", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01085-icon-service-Log-Analytics-Query-Pack.svg" + }, + { + "id": "azure:log-analytics-workspaces", + "subject": "analytics product or service", + "productName": "Log Analytics Workspaces", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/00009-icon-service-Log-Analytics-Workspaces.svg" + }, + { + "id": "azure:log-streaming", + "subject": "general product or service", + "productName": "Log Streaming", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10819-icon-service-Log-Streaming.svg" + }, + { + "id": "azure:logic-apps", + "subject": "integration product or service", + "productName": "Logic Apps", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02631-icon-service-Logic-Apps.svg" + }, + { + "id": "azure:logic-apps-custom-connector", + "subject": "integration product or service", + "productName": "Logic Apps Custom Connector", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10363-icon-service-Logic-Apps-Custom-Connector.svg" + }, + { + "id": "azure:logic-apps-template", + "subject": "integration product or service", + "productName": "Logic Apps Template", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/032130874-icon-service-Logic-Apps-Template.svg" + }, + { + "id": "azure:machine-learning", + "subject": "ai + machine learning product or service", + "productName": "Machine Learning", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10166-icon-service-Machine-Learning.svg" + }, + { + "id": "azure:machine-learning-studio-classic-web-services", + "subject": "ai + machine learning product or service", + "productName": "Machine Learning Studio (Classic) Web Services", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00030-icon-service-Machine-Learning-Studio-(Classic)-Web-Services.svg" + }, + { + "id": "azure:machine-learning-studio-web-service-plans", + "subject": "ai + machine learning product or service", + "productName": "Machine Learning Studio Web Service Plans", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10168-icon-service-Machine-Learning-Studio-Web-Service-Plans.svg" + }, + { + "id": "azure:machine-learning-studio-workspaces", + "subject": "ai + machine learning product or service", + "productName": "Machine Learning Studio Workspaces", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/10167-icon-service-Machine-Learning-Studio-Workspaces.svg" + }, + { + "id": "azure:machinesazurearc", + "subject": "management + governance product or service", + "productName": "MachinesAzureArc", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10450-icon-service-MachinesAzureArc.svg" + }, + { + "id": "azure:maintenance-configuration", + "subject": "compute product or service", + "productName": "Maintenance Configuration", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00195-icon-service-Maintenance-Configuration.svg" + }, + { + "id": "azure:managed-applications-center", + "subject": "management + governance product or service", + "productName": "Managed Applications Center", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10313-icon-service-Managed-Applications-Center.svg" + }, + { + "id": "azure:managed-database", + "subject": "databases product or service", + "productName": "Managed Database", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10135-icon-service-Managed-Database.svg" + }, + { + "id": "azure:managed-desktop", + "subject": "management + governance product or service", + "productName": "Managed Desktop", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10311-icon-service-Managed-Desktop.svg" + }, + { + "id": "azure:managed-devops-pools", + "subject": "devops product or service", + "productName": "Managed DevOps Pools", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/03393-icon-service-Managed-DevOps-Pools.svg" + }, + { + "id": "azure:managed-file-shares", + "subject": "storage product or service", + "productName": "Managed File Shares", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/03549-icon-service-Managed-File-Shares.svg" + }, + { + "id": "azure:managed-identities", + "subject": "identity product or service", + "productName": "Managed Identities", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10227-icon-service-Managed-Identities.svg" + }, + { + "id": "azure:managed-instance-apache-cassandra", + "subject": "other product or service", + "productName": "Managed Instance Apache Cassandra", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02663-icon-service-Managed-Instance-Apache-Cassandra.svg" + }, + { + "id": "azure:managed-service-fabric", + "subject": "compute product or service", + "productName": "Managed Service Fabric", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02370-icon-service-Managed-Service-Fabric.svg" + }, + { + "id": "azure:management-groups", + "subject": "general product or service", + "productName": "Management Groups", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10011-icon-service-Management-Groups.svg" + }, + { + "id": "azure:management-portal", + "subject": "general product or service", + "productName": "Management Portal", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10820-icon-service-Management-Portal.svg" + }, + { + "id": "azure:marketplace", + "subject": "general product or service", + "productName": "Marketplace", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10008-icon-service-Marketplace.svg" + }, + { + "id": "azure:marketplace-management", + "subject": "general product or service", + "productName": "Marketplace Management", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10112-icon-service-Marketplace-Management.svg" + }, + { + "id": "azure:media", + "subject": "general product or service", + "productName": "Media", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10854-icon-service-Media.svg" + }, + { + "id": "azure:media-file", + "subject": "general product or service", + "productName": "Media File", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10821-icon-service-Media-File.svg" + }, + { + "id": "azure:medtech-service", + "subject": "other product or service", + "productName": "MedTech Service", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02660-icon-service-MedTech-Service.svg" + }, + { + "id": "azure:mesh-applications", + "subject": "compute product or service", + "productName": "Mesh Applications", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10024-icon-service-Mesh-Applications.svg" + }, + { + "id": "azure:metrics", + "subject": "management + governance product or service", + "productName": "Metrics", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00020-icon-service-Metrics.svg" + }, + { + "id": "azure:metrics-advisor", + "subject": "ai + machine learning product or service", + "productName": "Metrics Advisor", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/02409-icon-service-Metrics-Advisor.svg" + }, + { + "id": "azure:microsoft-defender-easm", + "subject": "security product or service", + "productName": "Microsoft Defender EASM", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/03336-icon-service-Microsoft-Defender-EASM.svg" + }, + { + "id": "azure:microsoft-defender-for-cloud", + "subject": "security product or service", + "productName": "Microsoft Defender for Cloud", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/10241-icon-service-Microsoft-Defender-for-Cloud.svg" + }, + { + "id": "azure:microsoft-defender-for-iot", + "subject": "security product or service", + "productName": "Microsoft Defender for IoT", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/02247-icon-service-Microsoft-Defender-for-IoT.svg" + }, + { + "id": "azure:microsoft-dev-box", + "subject": "other product or service", + "productName": "Microsoft Dev Box", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03250-icon-service-Microsoft-Dev-Box.svg" + }, + { + "id": "azure:microsoft-discovery", + "subject": "other product or service", + "productName": "Microsoft Discovery", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/032869111-icon-service-Microsoft-Discovery.svg" + }, + { + "id": "azure:mindaro", + "subject": "intune product or service", + "productName": "Mindaro", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10350-icon-service-Mindaro.svg" + }, + { + "id": "azure:mission-landing-zone", + "subject": "other product or service", + "productName": "Mission Landing Zone", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02793-icon-service-Mission-Landing-Zone.svg" + }, + { + "id": "azure:mobile", + "subject": "general product or service", + "productName": "Mobile", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10822-icon-service-Mobile.svg" + }, + { + "id": "azure:mobile-engagement", + "subject": "general product or service", + "productName": "Mobile Engagement", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10823-icon-service-Mobile-Engagement.svg" + }, + { + "id": "azure:mobile-networks", + "subject": "other product or service", + "productName": "Mobile Networks", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02794-icon-service-Mobile-Networks.svg" + }, + { + "id": "azure:modular-data-center", + "subject": "other product or service", + "productName": "Modular Data Center", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02323-icon-service-Modular-Data-Center.svg" + }, + { + "id": "azure:module", + "subject": "general product or service", + "productName": "Module", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10855-icon-service-Module.svg" + }, + { + "id": "azure:monitor", + "subject": "management + governance product or service", + "productName": "Monitor", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00001-icon-service-Monitor.svg" + }, + { + "id": "azure:monitor-health-models", + "subject": "other product or service", + "productName": "Monitor Health Models", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03528-icon-service-Monitor-Health-Models.svg" + }, + { + "id": "azure:multi-factor-authentication", + "subject": "identity product or service", + "productName": "Multi Factor Authentication", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03256-icon-service-Multi-Factor-Authentication.svg" + }, + { + "id": "azure:multi-tenancy", + "subject": "identity product or service", + "productName": "Multi Tenancy", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/00965-icon-service-Multi-Tenancy.svg" + }, + { + "id": "azure:multifactor-authentication", + "subject": "security product or service", + "productName": "Multifactor Authentication", + "recommendedNodeKind": "service", + "category": "security", + "archivePath": "Azure_Public_Service_Icons/Icons/security/03344-icon-service-Multifactor-Authentication.svg" + }, + { + "id": "azure:my-customers", + "subject": "management + governance product or service", + "productName": "My Customers", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00014-icon-service-My-Customers.svg" + }, + { + "id": "azure:nat", + "subject": "networking product or service", + "productName": "NAT", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10310-icon-service-NAT.svg" + }, + { + "id": "azure:network-foundation-hub", + "subject": "networking product or service", + "productName": "Network Foundation Hub", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03643-icon-service-Network-Foundation-Hub.svg" + }, + { + "id": "azure:network-interfaces", + "subject": "networking product or service", + "productName": "Network Interfaces", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10080-icon-service-Network-Interfaces.svg" + }, + { + "id": "azure:network-managers", + "subject": "other product or service", + "productName": "Network Managers", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02237-icon-service-Network-Managers.svg" + }, + { + "id": "azure:network-security-groups", + "subject": "networking product or service", + "productName": "Network Security Groups", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10067-icon-service-Network-Security-Groups.svg" + }, + { + "id": "azure:network-security-hub", + "subject": "networking product or service", + "productName": "Network Security Hub", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03650-icon-service-Network-Security-Hub.svg" + }, + { + "id": "azure:network-security-perimeters", + "subject": "other product or service", + "productName": "Network Security Perimeters", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02939-icon-service-Network-Security-Perimeters.svg" + }, + { + "id": "azure:network-watcher", + "subject": "monitor product or service", + "productName": "Network Watcher", + "recommendedNodeKind": "service", + "category": "monitor", + "archivePath": "Azure_Public_Service_Icons/Icons/monitor/10066-icon-service-Network-Watcher.svg" + }, + { + "id": "azure:notification-hub-namespaces", + "subject": "iot product or service", + "productName": "Notification Hub Namespaces", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10053-icon-service-Notification-Hub-Namespaces.svg" + }, + { + "id": "azure:notification-hubs", + "subject": "app services product or service", + "productName": "Notification Hubs", + "recommendedNodeKind": "service", + "category": "app services", + "archivePath": "Azure_Public_Service_Icons/Icons/app services/10045-icon-service-Notification-Hubs.svg" + }, + { + "id": "azure:on-premises-data-gateways", + "subject": "networking product or service", + "productName": "On Premises Data Gateways", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10070-icon-service-On-Premises-Data-Gateways.svg" + }, + { + "id": "azure:open-supply-chain-platform", + "subject": "other product or service", + "productName": "Open Supply Chain Platform", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02602-icon-service-Open-Supply-Chain-Platform.svg" + }, + { + "id": "azure:operation-log-classic", + "subject": "management + governance product or service", + "productName": "Operation Log (Classic)", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00024-icon-service-Operation-Log-(Classic).svg" + }, + { + "id": "azure:oracle-database", + "subject": "databases product or service", + "productName": "Oracle Database", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/03490-icon-service-Oracle-Database.svg" + }, + { + "id": "azure:os-images-classic", + "subject": "compute product or service", + "productName": "OS Images (Classic)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10027-icon-service-OS-Images-(Classic).svg" + }, + { + "id": "azure:osconfig", + "subject": "other product or service", + "productName": "OSConfig", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03365-icon-service-OSConfig.svg" + }, + { + "id": "azure:outbound-connection", + "subject": "blockchain product or service", + "productName": "Outbound Connection", + "recommendedNodeKind": "service", + "category": "blockchain", + "archivePath": "Azure_Public_Service_Icons/Icons/blockchain/10364-icon-service-Outbound-Connection.svg" + }, + { + "id": "azure:partner-namespace", + "subject": "integration product or service", + "productName": "Partner Namespace", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02266-icon-service-Partner-Namespace.svg" + }, + { + "id": "azure:partner-registration", + "subject": "integration product or service", + "productName": "Partner Registration", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02265-icon-service-Partner-Registration.svg" + }, + { + "id": "azure:partner-topic", + "subject": "integration product or service", + "productName": "Partner Topic", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02072-icon-service-Partner-Topic.svg" + }, + { + "id": "azure:peering-service", + "subject": "other product or service", + "productName": "Peering Service", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00970-icon-service-Peering-Service.svg" + }, + { + "id": "azure:peerings", + "subject": "other product or service", + "productName": "Peerings", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/01285-icon-service-Peerings.svg" + }, + { + "id": "azure:personalizers", + "subject": "ai + machine learning product or service", + "productName": "Personalizers", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00796-icon-service-Personalizers.svg" + }, + { + "id": "azure:planetary-computer-pro", + "subject": "ai + machine learning product or service", + "productName": "Planetary Computer Pro", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03755-icon-service-Planetary-Computer-Pro.svg" + }, + { + "id": "azure:policy", + "subject": "management + governance product or service", + "productName": "Policy", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10316-icon-service-Policy.svg" + }, + { + "id": "azure:power", + "subject": "general product or service", + "productName": "Power", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10824-icon-service-Power.svg" + }, + { + "id": "azure:power-bi-embedded", + "subject": "analytics product or service", + "productName": "Power BI Embedded", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/03332-icon-service-Power-BI-Embedded.svg" + }, + { + "id": "azure:power-platform", + "subject": "analytics product or service", + "productName": "Power Platform", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/03335-icon-service-Power-Platform.svg" + }, + { + "id": "azure:power-up", + "subject": "general product or service", + "productName": "Power Up", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10826-icon-service-Power-Up.svg" + }, + { + "id": "azure:powershell", + "subject": "general product or service", + "productName": "Powershell", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10825-icon-service-Powershell.svg" + }, + { + "id": "azure:preview-features", + "subject": "general product or service", + "productName": "Preview Features", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/00456-icon-service-Preview-Features.svg" + }, + { + "id": "azure:private-endpoints", + "subject": "other product or service", + "productName": "Private Endpoints", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02579-icon-service-Private-Endpoints.svg" + }, + { + "id": "azure:private-link", + "subject": "networking product or service", + "productName": "Private Link", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/00427-icon-service-Private-Link.svg" + }, + { + "id": "azure:private-link-service", + "subject": "networking product or service", + "productName": "Private Link Service", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/01105-icon-service-Private-Link-Service.svg" + }, + { + "id": "azure:private-link-services", + "subject": "analytics product or service", + "productName": "Private Link Services", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/02209-icon-service-Private-Link-Services.svg" + }, + { + "id": "azure:process-explorer", + "subject": "general product or service", + "productName": "Process Explorer", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10828-icon-service-Process-Explorer.svg" + }, + { + "id": "azure:production-ready-database", + "subject": "general product or service", + "productName": "Production Ready Database", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10829-icon-service-Production-Ready-Database.svg" + }, + { + "id": "azure:promethus", + "subject": "other product or service", + "productName": "promethus", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/033112809-icon-service-promethus.svg" + }, + { + "id": "azure:proximity-placement-groups", + "subject": "networking product or service", + "productName": "Proximity Placement Groups", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10365-icon-service-Proximity-Placement-Groups.svg" + }, + { + "id": "azure:public-ip-addresses", + "subject": "networking product or service", + "productName": "Public IP Addresses", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10069-icon-service-Public-IP-Addresses.svg" + }, + { + "id": "azure:public-ip-addresses-classic", + "subject": "networking product or service", + "productName": "Public IP Addresses (Classic)", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10068-icon-service-Public-IP-Addresses-(Classic).svg" + }, + { + "id": "azure:public-ip-prefixes", + "subject": "networking product or service", + "productName": "Public IP Prefixes", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10372-icon-service-Public-IP-Prefixes.svg" + }, + { + "id": "azure:pubsub", + "subject": "integration product or service", + "productName": "pubsub", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02987-icon-service-pubsub.svg" + }, + { + "id": "azure:qna-makers", + "subject": "ai + machine learning product or service", + "productName": "QnA Makers", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00799-icon-service-QnA-Makers.svg" + }, + { + "id": "azure:quickstart-center", + "subject": "general product or service", + "productName": "Quickstart Center", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10010-icon-service-Quickstart-Center.svg" + }, + { + "id": "azure:recent", + "subject": "general product or service", + "productName": "Recent", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10006-icon-service-Recent.svg" + }, + { + "id": "azure:recovery-services-vaults", + "subject": "management + governance product or service", + "productName": "Recovery Services Vaults", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00017-icon-service-Recovery-Services-Vaults.svg" + }, + { + "id": "azure:region-management", + "subject": "general product or service", + "productName": "Region Management", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10116-icon-service-Region-Management.svg" + }, + { + "id": "azure:relays", + "subject": "integration product or service", + "productName": "Relays", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10209-icon-service-Relays.svg" + }, + { + "id": "azure:remote-rendering", + "subject": "mixed reality product or service", + "productName": "Remote Rendering", + "recommendedNodeKind": "service", + "category": "mixed reality", + "archivePath": "Azure_Public_Service_Icons/Icons/mixed reality/00698-icon-service-Remote-Rendering.svg" + }, + { + "id": "azure:reservations", + "subject": "general product or service", + "productName": "Reservations", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10003-icon-service-Reservations.svg" + }, + { + "id": "azure:reserved-capacity", + "subject": "other product or service", + "productName": "Reserved Capacity", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02638-icon-service-Reserved-Capacity.svg" + }, + { + "id": "azure:reserved-ip-addresses-classic", + "subject": "networking product or service", + "productName": "Reserved IP Addresses (Classic)", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10371-icon-service-Reserved-IP-Addresses-(Classic).svg" + }, + { + "id": "azure:resiliency", + "subject": "new icons product or service", + "productName": "Resiliency", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/034923704-icon-service-Resiliency.svg" + }, + { + "id": "azure:resource-explorer", + "subject": "general product or service", + "productName": "Resource Explorer", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10349-icon-service-Resource-Explorer.svg" + }, + { + "id": "azure:resource-graph-explorer", + "subject": "management + governance product or service", + "productName": "Resource Graph Explorer", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10318-icon-service-Resource-Graph-Explorer.svg" + }, + { + "id": "azure:resource-group-list", + "subject": "general product or service", + "productName": "Resource Group List", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10830-icon-service-Resource-Group-List.svg" + }, + { + "id": "azure:resource-groups", + "subject": "general product or service", + "productName": "Resource Groups", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10007-icon-service-Resource-Groups.svg" + }, + { + "id": "azure:resource-guard", + "subject": "other product or service", + "productName": "Resource Guard", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02819-icon-service-Resource-Guard.svg" + }, + { + "id": "azure:resource-linked", + "subject": "general product or service", + "productName": "Resource Linked", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10831-icon-service-Resource-Linked.svg" + }, + { + "id": "azure:resource-management-private-link", + "subject": "networking product or service", + "productName": "Resource Management Private Link", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02145-icon-service-Resource-Management-Private-Link.svg" + }, + { + "id": "azure:resource-mover", + "subject": "other product or service", + "productName": "Resource Mover", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02200-icon-service-Resource-Mover.svg" + }, + { + "id": "azure:resources-provider", + "subject": "management + governance product or service", + "productName": "Resources Provider", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/03366-icon-service-Resources-Provider.svg" + }, + { + "id": "azure:restore-points", + "subject": "compute product or service", + "productName": "Restore Points", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02817-icon-service-Restore-Points.svg" + }, + { + "id": "azure:restore-points-collections", + "subject": "compute product or service", + "productName": "Restore Points Collections", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/02818-icon-service-Restore-Points-Collections.svg" + }, + { + "id": "azure:route-filters", + "subject": "networking product or service", + "productName": "Route Filters", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10071-icon-service-Route-Filters.svg" + }, + { + "id": "azure:route-tables", + "subject": "networking product or service", + "productName": "Route Tables", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10082-icon-service-Route-Tables.svg" + }, + { + "id": "azure:rtos", + "subject": "other product or service", + "productName": "RTOS", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10778-icon-service-RTOS.svg" + }, + { + "id": "azure:savings-plans", + "subject": "other product or service", + "productName": "Savings Plans", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02880-icon-service-Savings-Plans.svg" + }, + { + "id": "azure:scheduled-actions", + "subject": "compute product or service", + "productName": "Scheduled Actions", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/033049334-icon-service-Scheduled-Actions.svg" + }, + { + "id": "azure:scheduler", + "subject": "general product or service", + "productName": "Scheduler", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10833-icon-service-Scheduler.svg" + }, + { + "id": "azure:scheduler-job-collections", + "subject": "management + governance product or service", + "productName": "Scheduler Job Collections", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00010-icon-service-Scheduler-Job-Collections.svg" + }, + { + "id": "azure:scvmm-management-servers", + "subject": "other product or service", + "productName": "SCVMM Management Servers", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02503-icon-service-SCVMM-Management-Servers.svg" + }, + { + "id": "azure:search", + "subject": "general product or service", + "productName": "Search", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10834-icon-service-Search.svg" + }, + { + "id": "azure:search-grid", + "subject": "general product or service", + "productName": "Search Grid", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10856-icon-service-Search-Grid.svg" + }, + { + "id": "azure:security", + "subject": "identity product or service", + "productName": "Security", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/00321-icon-service-Security.svg" + }, + { + "id": "azure:security-baselines", + "subject": "intune product or service", + "productName": "Security Baselines", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10336-icon-service-Security-Baselines.svg" + }, + { + "id": "azure:sendgrid-accounts", + "subject": "integration product or service", + "productName": "SendGrid Accounts", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10220-icon-service-SendGrid-Accounts.svg" + }, + { + "id": "azure:server-farm", + "subject": "general product or service", + "productName": "Server Farm", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10835-icon-service-Server-Farm.svg" + }, + { + "id": "azure:serverless-search", + "subject": "ai + machine learning product or service", + "productName": "Serverless Search", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/03321-icon-service-Serverless-Search.svg" + }, + { + "id": "azure:service-catalog-mad", + "subject": "management + governance product or service", + "productName": "Service Catalog MAD", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00027-icon-service-Service-Catalog-MAD.svg" + }, + { + "id": "azure:service-endpoint-policies", + "subject": "networking product or service", + "productName": "Service Endpoint Policies", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10085-icon-service-Service-Endpoint-Policies.svg" + }, + { + "id": "azure:service-fabric-clusters", + "subject": "compute product or service", + "productName": "Service Fabric Clusters", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10036-icon-service-Service-Fabric-Clusters.svg" + }, + { + "id": "azure:service-group-relationships", + "subject": "management + governance product or service", + "productName": "Service Group Relationships", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/030777508-icon-service-Service-Group-Relationships.svg" + }, + { + "id": "azure:service-groups", + "subject": "containers product or service", + "productName": "Service Groups", + "recommendedNodeKind": "service", + "category": "containers", + "archivePath": "Azure_Public_Service_Icons/Icons/containers/029637767-icon-service-Service-Groups.svg" + }, + { + "id": "azure:service-health", + "subject": "general product or service", + "productName": "Service Health", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10004-icon-service-Service-Health.svg" + }, + { + "id": "azure:service-providers", + "subject": "management + governance product or service", + "productName": "Service Providers", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00025-icon-service-Service-Providers.svg" + }, + { + "id": "azure:shared-image-galleries", + "subject": "compute product or service", + "productName": "Shared Image Galleries", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10039-icon-service-Shared-Image-Galleries.svg" + }, + { + "id": "azure:signalr", + "subject": "web product or service", + "productName": "SignalR", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/10052-icon-service-SignalR.svg" + }, + { + "id": "azure:software-as-a-service", + "subject": "integration product or service", + "productName": "Software as a Service", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10213-icon-service-Software-as-a-Service.svg" + }, + { + "id": "azure:software-updates", + "subject": "intune product or service", + "productName": "Software Updates", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10335-icon-service-Software-Updates.svg" + }, + { + "id": "azure:solutions", + "subject": "management + governance product or service", + "productName": "Solutions", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00021-icon-service-Solutions.svg" + }, + { + "id": "azure:sonic-dash", + "subject": "other product or service", + "productName": "Sonic Dash", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02922-icon-service-Sonic-Dash.svg" + }, + { + "id": "azure:spatial-anchor-accounts", + "subject": "mixed reality product or service", + "productName": "Spatial Anchor Accounts", + "recommendedNodeKind": "service", + "category": "mixed reality", + "archivePath": "Azure_Public_Service_Icons/Icons/mixed reality/10352-icon-service-Spatial-Anchor-Accounts.svg" + }, + { + "id": "azure:speech-services", + "subject": "ai + machine learning product or service", + "productName": "Speech Services", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00797-icon-service-Speech-Services.svg" + }, + { + "id": "azure:spot-vm", + "subject": "networking product or service", + "productName": "Spot VM", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02695-icon-service-Spot-VM.svg" + }, + { + "id": "azure:spot-vmss", + "subject": "networking product or service", + "productName": "Spot VMSS", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02692-icon-service-Spot-VMSS.svg" + }, + { + "id": "azure:sql-data-warehouses", + "subject": "databases product or service", + "productName": "SQL Data Warehouses", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/00036-icon-service-SQL-Data-Warehouses.svg" + }, + { + "id": "azure:sql-database-fleet-manager", + "subject": "databases product or service", + "productName": "SQL Database Fleet Manager", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/03565-icon-service-SQL-Database-Fleet-Manager.svg" + }, + { + "id": "azure:sql-elastic-pools", + "subject": "databases product or service", + "productName": "SQL Elastic Pools", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10134-icon-service-SQL-Elastic-Pools.svg" + }, + { + "id": "azure:sql-managed-instance", + "subject": "databases product or service", + "productName": "SQL Managed Instance", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10136-icon-service-SQL-Managed-Instance.svg" + }, + { + "id": "azure:sql-server", + "subject": "databases product or service", + "productName": "SQL Server", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10132-icon-service-SQL-Server.svg" + }, + { + "id": "azure:sql-server-registries", + "subject": "databases product or service", + "productName": "SQL Server Registries", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10351-icon-service-SQL-Server-Registries.svg" + }, + { + "id": "azure:ssd", + "subject": "general product or service", + "productName": "SSD", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10837-icon-service-SSD.svg" + }, + { + "id": "azure:ssh-keys", + "subject": "other product or service", + "productName": "SSH Keys", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00412-icon-service-SSH-Keys.svg" + }, + { + "id": "azure:ssis-lift-and-shift-ir", + "subject": "databases product or service", + "productName": "SSIS Lift And Shift IR", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/02392-icon-service-SSIS-Lift-And-Shift-IR.svg" + }, + { + "id": "azure:stack-hci-premium", + "subject": "iot product or service", + "productName": "Stack HCI Premium", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/03466-icon-service-Stack-HCI-Premium.svg" + }, + { + "id": "azure:stage-maps", + "subject": "compute product or service", + "productName": "Stage Maps", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/030868929-icon-service-Stage-Maps.svg" + }, + { + "id": "azure:static-apps", + "subject": "web product or service", + "productName": "Static Apps", + "recommendedNodeKind": "service", + "category": "web", + "archivePath": "Azure_Public_Service_Icons/Icons/web/01007-icon-service-Static-Apps.svg" + }, + { + "id": "azure:storage-accounts", + "subject": "storage product or service", + "productName": "Azure Storage Accounts", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10086-icon-service-Storage-Accounts.svg" + }, + { + "id": "azure:storage-accounts-classic", + "subject": "storage product or service", + "productName": "Storage Accounts (Classic)", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10087-icon-service-Storage-Accounts-(Classic).svg" + }, + { + "id": "azure:storage-actions", + "subject": "storage product or service", + "productName": "Storage Actions", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/03502-icon-service-Storage-Actions.svg" + }, + { + "id": "azure:storage-azure-files", + "subject": "general product or service", + "productName": "Storage Azure Files", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10838-icon-service-Storage-Azure-Files.svg" + }, + { + "id": "azure:storage-container", + "subject": "general product or service", + "productName": "Storage Container", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10839-icon-service-Storage-Container.svg" + }, + { + "id": "azure:storage-explorer", + "subject": "storage product or service", + "productName": "Storage Explorer", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10091-icon-service-Storage-Explorer.svg" + }, + { + "id": "azure:storage-functions", + "subject": "other product or service", + "productName": "Storage Functions", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02909-icon-service-Storage-Functions.svg" + }, + { + "id": "azure:storage-hubs", + "subject": "storage product or service", + "productName": "Storage Hubs", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/030486388-icon-service-Storage-Hubs.svg" + }, + { + "id": "azure:storage-queue", + "subject": "general product or service", + "productName": "Storage Queue", + "recommendedNodeKind": "queue", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10840-icon-service-Storage-Queue.svg" + }, + { + "id": "azure:storage-sync-services", + "subject": "storage product or service", + "productName": "Storage Sync Services", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10093-icon-service-Storage-Sync-Services.svg" + }, + { + "id": "azure:storsimple-data-managers", + "subject": "storage product or service", + "productName": "StorSimple Data Managers", + "recommendedNodeKind": "storage", + "category": "storage", + "archivePath": "Azure_Public_Service_Icons/Icons/storage/10092-icon-service-StorSimple-Data-Managers.svg" + }, + { + "id": "azure:storsimple-device-managers", + "subject": "integration product or service", + "productName": "StorSimple Device Managers", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/10089-icon-service-StorSimple-Device-Managers.svg" + }, + { + "id": "azure:stream-analytics-jobs", + "subject": "analytics product or service", + "productName": "Stream Analytics Jobs", + "recommendedNodeKind": "service", + "category": "analytics", + "archivePath": "Azure_Public_Service_Icons/Icons/analytics/00042-icon-service-Stream-Analytics-Jobs.svg" + }, + { + "id": "azure:subnet", + "subject": "networking product or service", + "productName": "Subnet", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02742-icon-service-Subnet.svg" + }, + { + "id": "azure:subscriptions", + "subject": "general product or service", + "productName": "Subscriptions", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10002-icon-service-Subscriptions.svg" + }, + { + "id": "azure:system-topic", + "subject": "integration product or service", + "productName": "System Topic", + "recommendedNodeKind": "service", + "category": "integration", + "archivePath": "Azure_Public_Service_Icons/Icons/integration/02073-icon-service-System-Topic.svg" + }, + { + "id": "azure:table", + "subject": "general product or service", + "productName": "Table", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10841-icon-service-Table.svg" + }, + { + "id": "azure:tag", + "subject": "general product or service", + "productName": "Tag", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10014-icon-service-Tag.svg" + }, + { + "id": "azure:tags", + "subject": "general product or service", + "productName": "Tags", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10842-icon-service-Tags.svg" + }, + { + "id": "azure:targets-management", + "subject": "other product or service", + "productName": "Targets Management", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02908-icon-service-Targets-Management.svg" + }, + { + "id": "azure:template-specs", + "subject": "other product or service", + "productName": "Template Specs", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02340-icon-service-Template-Specs.svg" + }, + { + "id": "azure:templates", + "subject": "general product or service", + "productName": "Templates", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10009-icon-service-Templates.svg" + }, + { + "id": "azure:tenant-properties", + "subject": "identity product or service", + "productName": "Tenant Properties", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/02679-icon-service-Tenant-Properties.svg" + }, + { + "id": "azure:tenant-status", + "subject": "intune product or service", + "productName": "Tenant Status", + "recommendedNodeKind": "service", + "category": "intune", + "archivePath": "Azure_Public_Service_Icons/Icons/intune/10342-icon-service-Tenant-Status.svg" + }, + { + "id": "azure:test-base", + "subject": "other product or service", + "productName": "Test Base", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02691-icon-service-Test-Base.svg" + }, + { + "id": "azure:tfs-vc-repository", + "subject": "general product or service", + "productName": "TFS VC Repository", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10843-icon-service-TFS-VC-Repository.svg" + }, + { + "id": "azure:time-series-data-sets", + "subject": "iot product or service", + "productName": "Time Series Data Sets", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10198-icon-service-Time-Series-Data-Sets.svg" + }, + { + "id": "azure:time-series-insights-access-policies", + "subject": "iot product or service", + "productName": "Time Series Insights Access Policies", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10192-icon-service-Time-Series-Insights-Access-Policies.svg" + }, + { + "id": "azure:time-series-insights-environments", + "subject": "iot product or service", + "productName": "Time Series Insights Environments", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10181-icon-service-Time-Series-Insights-Environments.svg" + }, + { + "id": "azure:time-series-insights-event-sources", + "subject": "iot product or service", + "productName": "Time Series Insights Event Sources", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10188-icon-service-Time-Series-Insights-Event-Sources.svg" + }, + { + "id": "azure:toolbox", + "subject": "general product or service", + "productName": "Toolbox", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10844-icon-service-Toolbox.svg" + }, + { + "id": "azure:toolchain-orchestrator", + "subject": "new icons product or service", + "productName": "Toolchain Orchestrator", + "recommendedNodeKind": "service", + "category": "new icons", + "archivePath": "Azure_Public_Service_Icons/Icons/new icons/029109619-icon-service-Toolchain-Orchestrator.svg" + }, + { + "id": "azure:traffic-manager-profiles", + "subject": "networking product or service", + "productName": "Traffic Manager Profiles", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10065-icon-service-Traffic-Manager-Profiles.svg" + }, + { + "id": "azure:translator-text", + "subject": "ai + machine learning product or service", + "productName": "Translator Text", + "recommendedNodeKind": "service", + "category": "ai + machine learning", + "archivePath": "Azure_Public_Service_Icons/Icons/ai + machine learning/00800-icon-service-Translator-Text.svg" + }, + { + "id": "azure:troubleshoot", + "subject": "general product or service", + "productName": "Troubleshoot", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10341-icon-service-Troubleshoot.svg" + }, + { + "id": "azure:universal-print", + "subject": "management + governance product or service", + "productName": "Universal Print", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/00571-icon-service-Universal-Print.svg" + }, + { + "id": "azure:update-management-center", + "subject": "other product or service", + "productName": "Update Management Center", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02846-icon-service-Update-Management-Center.svg" + }, + { + "id": "azure:user-privacy", + "subject": "management + governance product or service", + "productName": "User Privacy", + "recommendedNodeKind": "service", + "category": "management + governance", + "archivePath": "Azure_Public_Service_Icons/Icons/management + governance/10303-icon-service-User-Privacy.svg" + }, + { + "id": "azure:user-settings", + "subject": "identity product or service", + "productName": "User Settings", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10433-icon-service-User-Settings.svg" + }, + { + "id": "azure:user-subscriptions", + "subject": "identity product or service", + "productName": "User Subscriptions", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10111-icon-service-User-Subscriptions.svg" + }, + { + "id": "azure:users", + "subject": "identity product or service", + "productName": "Users", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/10230-icon-service-Users.svg" + }, + { + "id": "azure:verifiable-credentials", + "subject": "identity product or service", + "productName": "Verifiable Credentials", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/01084-icon-service-Verifiable-Credentials.svg" + }, + { + "id": "azure:verification-as-a-service", + "subject": "identity product or service", + "productName": "Verification As A Service", + "recommendedNodeKind": "service", + "category": "identity", + "archivePath": "Azure_Public_Service_Icons/Icons/identity/03225-icon-service-Verification-As-A-Service.svg" + }, + { + "id": "azure:versions", + "subject": "general product or service", + "productName": "Versions", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10845-icon-service-Versions.svg" + }, + { + "id": "azure:video-analyzers", + "subject": "other product or service", + "productName": "Video Analyzers", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/00712-icon-service-Video-Analyzers.svg" + }, + { + "id": "azure:virtual-clusters", + "subject": "databases product or service", + "productName": "Virtual Clusters", + "recommendedNodeKind": "database", + "category": "databases", + "archivePath": "Azure_Public_Service_Icons/Icons/databases/10127-icon-service-Virtual-Clusters.svg" + }, + { + "id": "azure:virtual-instance-for-sap", + "subject": "other product or service", + "productName": "Virtual Instance for SAP", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03089-icon-service-Virtual-Instance-for-SAP.svg" + }, + { + "id": "azure:virtual-machines", + "subject": "compute product or service", + "productName": "Azure Virtual Machines", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10021-icon-service-Virtual-Machine.svg" + }, + { + "id": "azure:virtual-machines-classic", + "subject": "compute product or service", + "productName": "Virtual Machines (Classic)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10028-icon-service-Virtual-Machines-(Classic).svg" + }, + { + "id": "azure:virtual-network-gateways", + "subject": "networking product or service", + "productName": "Virtual Network Gateways", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10063-icon-service-Virtual-Network-Gateways.svg" + }, + { + "id": "azure:virtual-networks", + "subject": "networking product or service", + "productName": "Virtual Networks", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10061-icon-service-Virtual-Networks.svg" + }, + { + "id": "azure:virtual-networks-classic", + "subject": "networking product or service", + "productName": "Virtual Networks (Classic)", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10075-icon-service-Virtual-Networks-(Classic).svg" + }, + { + "id": "azure:virtual-router", + "subject": "networking product or service", + "productName": "Virtual Router", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/02496-icon-service-Virtual-Router.svg" + }, + { + "id": "azure:virtual-visits-builder", + "subject": "other product or service", + "productName": "Virtual Visits Builder", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02949-icon-service-Virtual-Visits-Builder.svg" + }, + { + "id": "azure:virtual-wan-hub", + "subject": "networking product or service", + "productName": "Virtual WAN Hub", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/00860-icon-service-Virtual-WAN-Hub.svg" + }, + { + "id": "azure:virtual-wans", + "subject": "networking product or service", + "productName": "Virtual WANs", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10353-icon-service-Virtual-WANs.svg" + }, + { + "id": "azure:vm-app-definitions", + "subject": "other product or service", + "productName": "VM App Definitions", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02805-icon-service-VM-App-Definitions.svg" + }, + { + "id": "azure:vm-app-versions", + "subject": "other product or service", + "productName": "VM App Versions", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02806-icon-service-VM-App-Versions.svg" + }, + { + "id": "azure:vm-image-version", + "subject": "other product or service", + "productName": "VM Image Version", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02866-icon-service-VM-Image-Version.svg" + }, + { + "id": "azure:vm-images-classic", + "subject": "compute product or service", + "productName": "VM Images (Classic)", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10040-icon-service-VM-Images-(Classic).svg" + }, + { + "id": "azure:vm-scale-sets", + "subject": "compute product or service", + "productName": "VM Scale Sets", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/10034-icon-service-VM-Scale-Sets.svg" + }, + { + "id": "azure:vnet-appliance", + "subject": "networking product or service", + "productName": "VNet Appliance", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/034412066-icon-service-VNet-Appliance.svg" + }, + { + "id": "azure:vpnclientwindows", + "subject": "networking product or service", + "productName": "VPNClientWindows", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/03694-icon-service-VPNClientWindows.svg" + }, + { + "id": "azure:wac", + "subject": "other product or service", + "productName": "WAC", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10355-icon-service-WAC.svg" + }, + { + "id": "azure:wac-installer", + "subject": "other product or service", + "productName": "WAC Installer", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/03563-icon-service-WAC-Installer.svg" + }, + { + "id": "azure:web-app-plus-database", + "subject": "other product or service", + "productName": "Web App + Database", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02515-icon-service-Web-App-+-Database.svg" + }, + { + "id": "azure:web-application-firewall-policies-waf", + "subject": "networking product or service", + "productName": "Web Application Firewall Policies(WAF)", + "recommendedNodeKind": "service", + "category": "networking", + "archivePath": "Azure_Public_Service_Icons/Icons/networking/10362-icon-service-Web-Application-Firewall-Policies(WAF).svg" + }, + { + "id": "azure:web-jobs", + "subject": "other product or service", + "productName": "Web Jobs", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/10846-icon-service-Web-Jobs.svg" + }, + { + "id": "azure:web-slots", + "subject": "general product or service", + "productName": "Web Slots", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10849-icon-service-Web-Slots.svg" + }, + { + "id": "azure:web-test", + "subject": "general product or service", + "productName": "Web Test", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10850-icon-service-Web-Test.svg" + }, + { + "id": "azure:website-power", + "subject": "general product or service", + "productName": "Website Power", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10847-icon-service-Website-Power.svg" + }, + { + "id": "azure:website-staging", + "subject": "general product or service", + "productName": "Website Staging", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10848-icon-service-Website-Staging.svg" + }, + { + "id": "azure:windows-notification-services", + "subject": "other product or service", + "productName": "Windows Notification Services", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02733-icon-service-Windows-Notification-Services.svg" + }, + { + "id": "azure:windows10-core-services", + "subject": "iot product or service", + "productName": "Windows10 Core Services", + "recommendedNodeKind": "service", + "category": "iot", + "archivePath": "Azure_Public_Service_Icons/Icons/iot/10203-icon-service-Windows10-Core-Services.svg" + }, + { + "id": "azure:workbooks", + "subject": "general product or service", + "productName": "Workbooks", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10851-icon-service-Workbooks.svg" + }, + { + "id": "azure:worker-container-app", + "subject": "other product or service", + "productName": "Worker Container App", + "recommendedNodeKind": "service", + "category": "other", + "archivePath": "Azure_Public_Service_Icons/Icons/other/02884-icon-service-Worker-Container-App.svg" + }, + { + "id": "azure:workflow", + "subject": "general product or service", + "productName": "Workflow", + "recommendedNodeKind": "service", + "category": "general", + "archivePath": "Azure_Public_Service_Icons/Icons/general/10852-icon-service-Workflow.svg" + }, + { + "id": "azure:workload-orchestration", + "subject": "hybrid + multicloud product or service", + "productName": "Workload Orchestration", + "recommendedNodeKind": "service", + "category": "hybrid + multicloud", + "archivePath": "Azure_Public_Service_Icons/Icons/hybrid + multicloud/029109619-icon-service-Workload-Orchestration.svg" + }, + { + "id": "azure:workspace-gateway", + "subject": "devops product or service", + "productName": "Workspace Gateway", + "recommendedNodeKind": "service", + "category": "devops", + "archivePath": "Azure_Public_Service_Icons/Icons/devops/03623-icon-service-Workspace-Gateway.svg" + }, + { + "id": "azure:workspaces", + "subject": "compute product or service", + "productName": "Workspaces", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00330-icon-service-Workspaces.svg" + }, + { + "id": "azure:workspaces-00400", + "subject": "compute product or service", + "productName": "Workspaces", + "recommendedNodeKind": "service", + "category": "compute", + "archivePath": "Azure_Public_Service_Icons/Icons/compute/00400-icon-service-Workspaces.svg" + } + ] +} diff --git a/catalogs/gcp.json b/catalogs/gcp.json new file mode 100644 index 0000000..ff17667 --- /dev/null +++ b/catalogs/gcp.json @@ -0,0 +1,454 @@ +{ + "catalogVersion": "1.0", + "packVersion": "0.2.0", + "provider": { + "id": "gcp", + "name": "Google Cloud" + }, + "source": { + "pageUrl": "https://cloud.google.com/icons", + "archiveUrl": "https://services.google.com/fh/files/misc/core-products-icons.zip", + "archiveSha256": "sha256:6531a10f58bc599c24d9a455d81dd757c1a03c3c43da9cddf639b859c1c1eece", + "release": "Core product icons (May 2026 guide)", + "retrievedAt": "2026-09-04", + "termsUrl": "https://about.google/brand-resource-center/", + "termsReviewedAt": "2026-09-04", + "reviewAfter": "2026-12-03", + "copyright": "Copyright Google LLC", + "licenseId": "LicenseRef-Google-Cloud-Product-Icons-Terms", + "archiveLicenseIncluded": false + }, + "additionalSources": [ + { + "id": "categories", + "pageUrl": "https://cloud.google.com/icons", + "archiveUrl": "https://services.google.com/fh/files/misc/category-icons.zip", + "archiveSha256": "sha256:e5bc3abd3527dc2500e9bff7f15870783e2c764129c49b7cd4c1b4e105345002", + "release": "Product category icons (May 2026 guide)", + "retrievedAt": "2026-09-04", + "termsUrl": "https://about.google/brand-resource-center/", + "termsReviewedAt": "2026-09-04", + "reviewAfter": "2026-12-03", + "copyright": "Copyright Google LLC", + "licenseId": "LicenseRef-Google-Cloud-Product-Icons-Terms", + "archiveLicenseIncluded": false + } + ], + "rights": { + "termsAcceptanceRequired": true, + "permittedOutputs": [ + "architecture-diagram", + "documentation" + ], + "redistribution": { + "cargo": false, + "npm": false, + "wasm": false, + "webAsset": false, + "nativeBinary": false, + "generatedOutput": true + }, + "processing": { + "localOnly": true, + "automaticDownload": false, + "serverUpload": false, + "preserveColors": true, + "preserveGeometry": true, + "productNameNearby": true + }, + "modificationPolicy": "visual-preservation-only" + }, + "notice": { + "attribution": "Google Cloud product icons are owned by Google LLC.", + "termsSummary": "Use is limited to diagrams and technical documentation described by the official Google Cloud Icon Library and applicable Google brand terms.", + "nonEndorsement": "Google does not sponsor or endorse this diagram or Stack." + }, + "icons": [ + { + "id": "gcp:agents", + "subject": "Google Cloud product category", + "productName": "Agents category", + "recommendedNodeKind": "worker", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Agents/SVG/Agents-512-color.svg" + }, + { + "id": "gcp:ai-and-machine-learning", + "subject": "Google Cloud product category", + "productName": "AI & Machine Learning category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/AI _ Machine Learning/SVG/AIMachineLearning-512-color.svg" + }, + { + "id": "gcp:ai-hypercomputer", + "subject": "Google Cloud core product", + "productName": "AI Hypercomputer", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/AI Hypercomputer/SVG/AIHypercomputer-512-color.svg" + }, + { + "id": "gcp:alloydb", + "subject": "Google Cloud core product", + "productName": "AlloyDB", + "recommendedNodeKind": "database", + "category": "Core products", + "archivePath": "Unique Icons/AlloyDB/SVG/AlloyDB-512-color.svg" + }, + { + "id": "gcp:anthos", + "subject": "Google Cloud core product", + "productName": "Anthos", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Anthos/SVG/Anthos-512-color.svg" + }, + { + "id": "gcp:apigee", + "subject": "Google Cloud core product", + "productName": "Apigee", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Apigee/SVG/Apigee-512-color-rgb.svg" + }, + { + "id": "gcp:bigquery", + "subject": "Google Cloud core product", + "productName": "BigQuery", + "recommendedNodeKind": "database", + "category": "Core products", + "archivePath": "Unique Icons/BigQuery/SVG/BigQuery-512-color.svg" + }, + { + "id": "gcp:business-intelligence", + "subject": "Google Cloud product category", + "productName": "Business Intelligence category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Business Intelligence/SVG/BusinessIntelligence-512-color.svg" + }, + { + "id": "gcp:cloud-run", + "subject": "Google Cloud core product", + "productName": "Cloud Run", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Cloud Run/SVG/CloudRun-512-color-rgb.svg" + }, + { + "id": "gcp:cloud-spanner", + "subject": "Google Cloud core product", + "productName": "Cloud Spanner", + "recommendedNodeKind": "database", + "category": "Core products", + "archivePath": "Unique Icons/Cloud Spanner/SVG/CloudSpanner-512-color.svg" + }, + { + "id": "gcp:cloud-sql", + "subject": "Google Cloud core product", + "productName": "Cloud SQL", + "recommendedNodeKind": "database", + "category": "Core products", + "archivePath": "Unique Icons/Cloud SQL/SVG/CloudSQL-512-color.svg" + }, + { + "id": "gcp:cloud-storage", + "subject": "Google Cloud core product", + "productName": "Cloud Storage", + "recommendedNodeKind": "storage", + "category": "Core products", + "archivePath": "Unique Icons/Cloud Storage/SVG/Cloud_Storage-512-color.svg" + }, + { + "id": "gcp:collaboration", + "subject": "Google Cloud product category", + "productName": "Collaboration category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Collaboration/SVG/Collaboration-512-color.svg" + }, + { + "id": "gcp:compute", + "subject": "Google Cloud product category", + "productName": "Compute category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Compute/SVG/Compute-512-color.svg" + }, + { + "id": "gcp:compute-engine", + "subject": "Google Cloud core product", + "productName": "Compute Engine", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Compute Engine/SVG/ComputeEngine-512-color-rgb.svg" + }, + { + "id": "gcp:containers", + "subject": "Google Cloud product category", + "productName": "Containers category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Containers/SVG/Containers-512-color.svg" + }, + { + "id": "gcp:data-analytics", + "subject": "Google Cloud product category", + "productName": "Data Analytics category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Data Analytics/SVG/DataAnalytics-512-color.svg" + }, + { + "id": "gcp:databases", + "subject": "Google Cloud product category", + "productName": "Databases category", + "recommendedNodeKind": "database", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Databases/SVG/Databases-512-color.svg" + }, + { + "id": "gcp:developer-tools", + "subject": "Google Cloud product category", + "productName": "Developer Tools category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Developer Tools/SVG/Developer_Tools-512-color.svg" + }, + { + "id": "gcp:devops", + "subject": "Google Cloud product category", + "productName": "DevOps category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/DevOps/SVG/DevOps-512-color.svg" + }, + { + "id": "gcp:distributed-cloud", + "subject": "Google Cloud core product", + "productName": "Distributed Cloud", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Distributed Cloud/SVG/DistributedCloud-512-color.svg" + }, + { + "id": "gcp:gke", + "subject": "Google Cloud core product", + "productName": "Google Kubernetes Engine", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/GKE/SVG/GKE-512-color.svg" + }, + { + "id": "gcp:hybrid-and-multicloud", + "subject": "Google Cloud product category", + "productName": "Hybrid & Multicloud category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Hybrid & Multicloud/SVG/HybridMulticloud-512-color.svg" + }, + { + "id": "gcp:hyperdisk", + "subject": "Google Cloud core product", + "productName": "Hyperdisk", + "recommendedNodeKind": "storage", + "category": "Core products", + "archivePath": "Unique Icons/Hyperdisk/SVG/Hyperdisk-512-color.svg" + }, + { + "id": "gcp:integration-services", + "subject": "Google Cloud product category", + "productName": "Integration Services category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Integration Services/SVG/IntegrationServices-512-color.svg" + }, + { + "id": "gcp:looker", + "subject": "Google Cloud core product", + "productName": "Looker", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Looker/SVG/Looker-512-color.svg" + }, + { + "id": "gcp:management-tools", + "subject": "Google Cloud product category", + "productName": "Management Tools category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Management Tools/SVG/ManagementTools-512-color.svg" + }, + { + "id": "gcp:mandiant", + "subject": "Google Cloud core product", + "productName": "Mandiant", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Mandiant/SVG/Mandiant-512-color.svg" + }, + { + "id": "gcp:maps-and-geospatial", + "subject": "Google Cloud product category", + "productName": "Maps & Geospatial category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Maps & Geospatial/SVG/MapsGeospatial-512-color.svg" + }, + { + "id": "gcp:marketplace", + "subject": "Google Cloud product category", + "productName": "Marketplace category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Marketplace/SVG/Marketplace-512-color.svg" + }, + { + "id": "gcp:media-services", + "subject": "Google Cloud product category", + "productName": "Media Services category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Media Services/SVG/MediaServices-512-color.svg" + }, + { + "id": "gcp:migration", + "subject": "Google Cloud product category", + "productName": "Migration category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Migration/SVG/Migration-512-color.svg" + }, + { + "id": "gcp:mixed-reality", + "subject": "Google Cloud product category", + "productName": "Mixed Reality category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Mixed Reality/SVG/MixedReality-512-color.svg" + }, + { + "id": "gcp:networking", + "subject": "Google Cloud product category", + "productName": "Networking category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Networking/SVG/Networking-512-color-rgb.svg" + }, + { + "id": "gcp:observability", + "subject": "Google Cloud product category", + "productName": "Observability category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Observability/SVG/Observability-512-color.svg" + }, + { + "id": "gcp:operations", + "subject": "Google Cloud product category", + "productName": "Operations category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Operations/SVG/Operations-512-color.svg" + }, + { + "id": "gcp:security-command-center", + "subject": "Google Cloud core product", + "productName": "Security Command Center", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Security Command Center/SVG/SecurityCommandCenter-512-color.svg" + }, + { + "id": "gcp:security-identity", + "subject": "Google Cloud product category", + "productName": "Security Identity category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Security Identity/SVG/SecurityIdentity-512-color.svg" + }, + { + "id": "gcp:security-operations", + "subject": "Google Cloud core product", + "productName": "Security Operations", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Security Operations/SVG/SecOps-512-color-rgb.svg" + }, + { + "id": "gcp:serverless", + "subject": "Google Cloud product category", + "productName": "Serverless Computing category", + "recommendedNodeKind": "function", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Serverless Computing/SVG/ServerlessComputing-512-color.svg" + }, + { + "id": "gcp:storage", + "subject": "Google Cloud product category", + "productName": "Storage category", + "recommendedNodeKind": "storage", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Storage/SVG/Storage-512-color.svg" + }, + { + "id": "gcp:threat-intelligence", + "subject": "Google Cloud core product", + "productName": "Threat Intelligence", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Threat Intelligence/SVG/ThreatIntelligence-512-color.svg" + }, + { + "id": "gcp:vertex-ai", + "subject": "Google Cloud core product", + "productName": "Vertex AI", + "recommendedNodeKind": "service", + "category": "Core products", + "archivePath": "Unique Icons/Vertex AI/SVG/VertexAI-512-color.svg" + }, + { + "id": "gcp:web-and-mobile", + "subject": "Google Cloud product category", + "productName": "Web & Mobile category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Web & Mobile/SVG/WebMobile-512-color.svg" + }, + { + "id": "gcp:web3", + "subject": "Google Cloud product category", + "productName": "Web3 category", + "recommendedNodeKind": "service", + "category": "Product categories", + "sourceId": "categories", + "archivePath": "Category Icons/Web3/SVG/Web3-512-color.svg" + } + ] +} diff --git a/catalogs/simple-icons.json b/catalogs/simple-icons.json new file mode 100644 index 0000000..4ca9811 --- /dev/null +++ b/catalogs/simple-icons.json @@ -0,0 +1,674 @@ +{ + "catalogVersion": "1.0", + "packVersion": "0.2.0", + "provider": { + "id": "simple-icons", + "name": "Simple Icons (curated tools)" + }, + "source": { + "pageUrl": "https://simpleicons.org/", + "archiveUrl": "https://github.com/simple-icons/simple-icons/archive/refs/tags/16.29.0.zip", + "archiveSha256": "sha256:99f30fabd5be19dab51e09b2adebb6fe54fce1f3709ddfdc936a1338dfebc68d", + "release": "16.29.0", + "retrievedAt": "2026-09-04", + "termsUrl": "https://github.com/simple-icons/simple-icons/blob/16.29.0/DISCLAIMER.md", + "termsReviewedAt": "2026-09-04", + "reviewAfter": "2026-12-03", + "copyright": "Simple Icons contributors and the respective trademark owners", + "licenseId": "LicenseRef-Simple-Icons-CC0-and-Brand-Rights", + "archiveLicenseIncluded": true + }, + "additionalSources": [], + "rights": { + "termsAcceptanceRequired": true, + "permittedOutputs": [ + "architecture-diagram", + "documentation", + "presentation" + ], + "redistribution": { + "cargo": false, + "npm": false, + "wasm": false, + "webAsset": false, + "nativeBinary": false, + "generatedOutput": true + }, + "processing": { + "localOnly": true, + "automaticDownload": false, + "serverUpload": false, + "preserveColors": true, + "preserveGeometry": true, + "productNameNearby": true + }, + "modificationPolicy": "visual-preservation-only" + }, + "notice": { + "attribution": "Glyphs are sourced from Simple Icons 16.29.0. Product names and marks belong to their respective owners.", + "termsSummary": "Simple Icons is CC0, but that does not imply that every included brand icon is CC0. Review each icon's recorded brand source and guidelines before use.", + "nonEndorsement": "Simple Icons and the named brands do not sponsor or endorse this diagram or Stack." + }, + "icons": [ + { + "id": "simple-icons:1password", + "subject": "Collaboration tool or service", + "productName": "1Password", + "brandSourceUrl": "https://1password.com/press", + "brandGuidelinesUrl": "https://1password.com/press", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/1password.svg" + }, + { + "id": "simple-icons:ansible", + "subject": "Infrastructure tool or service", + "productName": "Ansible", + "brandSourceUrl": "https://www.ansible.com/logos", + "brandGuidelinesUrl": "https://www.ansible.com/logos", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/ansible.svg" + }, + { + "id": "simple-icons:apacheairflow", + "subject": "Data tool or service", + "productName": "Apache Airflow", + "brandSourceUrl": "https://apache.org/logos", + "brandGuidelinesUrl": "https://www.apache.org/foundation/marks", + "recommendedNodeKind": "service", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/apacheairflow.svg" + }, + { + "id": "simple-icons:apachekafka", + "subject": "Data tool or service", + "productName": "Apache Kafka", + "brandSourceUrl": "https://apache.org/logos", + "brandGuidelinesUrl": "https://www.apache.org/foundation/marks", + "recommendedNodeKind": "queue", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/apachekafka.svg" + }, + { + "id": "simple-icons:argo", + "subject": "Infrastructure tool or service", + "productName": "Argo", + "brandSourceUrl": "https://github.com/cncf/artwork/blob/c2e619cdf85e8bac090ceca7c0834c5cfedf9426/projects/argo/icon/black/argo-icon-black.svg", + "brandGuidelinesUrl": "https://github.com/cncf/artwork/blob/c2e619cdf85e8bac090ceca7c0834c5cfedf9426/projects/argo/icon/black/argo-icon-black.svg", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/argo.svg" + }, + { + "id": "simple-icons:atlassian", + "subject": "Collaboration tool or service", + "productName": "Atlassian", + "brandSourceUrl": "https://atlassian.design/resources/logo-library", + "brandGuidelinesUrl": "https://atlassian.design/foundations/logos", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/atlassian.svg" + }, + { + "id": "simple-icons:auth0", + "subject": "Identity tool or service", + "productName": "Auth0", + "brandSourceUrl": "https://auth0.com", + "brandGuidelinesUrl": "https://auth0.com", + "recommendedNodeKind": "external", + "category": "Identity", + "archivePath": "simple-icons-16.29.0/icons/auth0.svg" + }, + { + "id": "simple-icons:bitbucket", + "subject": "Collaboration tool or service", + "productName": "Bitbucket", + "brandSourceUrl": "https://atlassian.design/resources/logo-library", + "brandGuidelinesUrl": "https://atlassian.design/foundations/logos", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/bitbucket.svg" + }, + { + "id": "simple-icons:bun", + "subject": "Development tool or service", + "productName": "Bun", + "brandSourceUrl": "https://bun.sh/press-kit", + "brandGuidelinesUrl": "https://bun.sh/press-kit", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/bun.svg" + }, + { + "id": "simple-icons:circleci", + "subject": "Infrastructure tool or service", + "productName": "CircleCI", + "brandSourceUrl": "https://circleci.com/press", + "brandGuidelinesUrl": "https://circleci.com/press", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/circleci.svg" + }, + { + "id": "simple-icons:cloudflare", + "subject": "Infrastructure tool or service", + "productName": "Cloudflare", + "brandSourceUrl": "https://www.cloudflare.com/logo/", + "brandGuidelinesUrl": "https://www.cloudflare.com/trademark/", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/cloudflare.svg" + }, + { + "id": "simple-icons:confluence", + "subject": "Collaboration tool or service", + "productName": "Confluence", + "brandSourceUrl": "https://www.atlassian.com/company/news/press-kit", + "brandGuidelinesUrl": "https://www.atlassian.com/company/news/press-kit", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/confluence.svg" + }, + { + "id": "simple-icons:datadog", + "subject": "Observability tool or service", + "productName": "Datadog", + "brandSourceUrl": "https://www.datadoghq.com/about/resources", + "brandGuidelinesUrl": "https://www.datadoghq.com/about/resources/", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/datadog.svg" + }, + { + "id": "simple-icons:deno", + "subject": "Development tool or service", + "productName": "Deno", + "brandSourceUrl": "https://github.com/denoland/docs/blob/5dee713844c7447f80acd4093caa9d350d80bf36/static/img/logo.svg", + "brandGuidelinesUrl": "https://deno.com/brand", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/deno.svg" + }, + { + "id": "simple-icons:discord", + "subject": "Collaboration tool or service", + "productName": "Discord", + "brandSourceUrl": "https://discord.com/branding", + "brandGuidelinesUrl": "https://discord.com/branding", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/discord.svg" + }, + { + "id": "simple-icons:docker", + "subject": "Infrastructure tool or service", + "productName": "Docker", + "brandSourceUrl": "https://www.docker.com/company/newsroom/media-resources", + "brandGuidelinesUrl": "https://www.docker.com/company/newsroom/media-resources", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/docker.svg" + }, + { + "id": "simple-icons:elastic", + "subject": "Data tool or service", + "productName": "Elastic", + "brandSourceUrl": "https://www.elastic.co/brand", + "brandGuidelinesUrl": "https://www.elastic.co/brand", + "recommendedNodeKind": "service", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/elastic.svg" + }, + { + "id": "simple-icons:figma", + "subject": "Collaboration tool or service", + "productName": "Figma", + "brandSourceUrl": "https://www.figma.com/using-the-figma-brand/", + "brandGuidelinesUrl": "https://www.figma.com/using-the-figma-brand/", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/figma.svg" + }, + { + "id": "simple-icons:firebase", + "subject": "Data tool or service", + "productName": "Firebase", + "brandSourceUrl": "https://firebase.google.com/brand-guidelines", + "brandGuidelinesUrl": "https://firebase.google.com/brand-guidelines", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/firebase.svg" + }, + { + "id": "simple-icons:git", + "subject": "Development tool or service", + "productName": "Git", + "brandSourceUrl": "https://git-scm.com/community/logos", + "brandGuidelinesUrl": "https://git-scm.com/community/logos", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/git.svg" + }, + { + "id": "simple-icons:github", + "subject": "Collaboration tool or service", + "productName": "GitHub", + "brandSourceUrl": "https://github.com/logos", + "brandGuidelinesUrl": "https://github.com/logos", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/github.svg" + }, + { + "id": "simple-icons:githubactions", + "subject": "Collaboration tool or service", + "productName": "GitHub Actions", + "brandSourceUrl": "https://github.com/features/actions", + "brandGuidelinesUrl": "https://github.com/features/actions", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/githubactions.svg" + }, + { + "id": "simple-icons:gitlab", + "subject": "Collaboration tool or service", + "productName": "GitLab", + "brandSourceUrl": "https://about.gitlab.com/press/press-kit/", + "brandGuidelinesUrl": "https://about.gitlab.com/handbook/marketing/corporate-marketing/brand-activation/trademark-guidelines/", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/gitlab.svg" + }, + { + "id": "simple-icons:go", + "subject": "Development tool or service", + "productName": "Go", + "brandSourceUrl": "https://blog.golang.org/go-brand", + "brandGuidelinesUrl": "https://blog.golang.org/go-brand", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/go.svg" + }, + { + "id": "simple-icons:grafana", + "subject": "Observability tool or service", + "productName": "Grafana", + "brandSourceUrl": "https://grafana.com", + "brandGuidelinesUrl": "https://grafana.com", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/grafana.svg" + }, + { + "id": "simple-icons:helm", + "subject": "Infrastructure tool or service", + "productName": "Helm", + "brandSourceUrl": "https://helm.sh", + "brandGuidelinesUrl": "https://helm.sh", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/helm.svg" + }, + { + "id": "simple-icons:jenkins", + "subject": "Infrastructure tool or service", + "productName": "Jenkins", + "brandSourceUrl": "https://get.jenkins.io/art/", + "brandGuidelinesUrl": "https://www.jenkins.io/press/", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/jenkins.svg" + }, + { + "id": "simple-icons:jira", + "subject": "Collaboration tool or service", + "productName": "Jira", + "brandSourceUrl": "https://atlassian.design/resources/logo-library", + "brandGuidelinesUrl": "https://atlassian.design/foundations/logos/", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/jira.svg" + }, + { + "id": "simple-icons:kubernetes", + "subject": "Infrastructure tool or service", + "productName": "Kubernetes", + "brandSourceUrl": "https://github.com/kubernetes/kubernetes/tree/cac53883f4714452f3084a22e4be20d042a9df33/logo", + "brandGuidelinesUrl": "https://github.com/kubernetes/kubernetes/tree/cac53883f4714452f3084a22e4be20d042a9df33/logo", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/kubernetes.svg" + }, + { + "id": "simple-icons:linear", + "subject": "Collaboration tool or service", + "productName": "Linear", + "brandSourceUrl": "https://linear.app", + "brandGuidelinesUrl": "https://linear.app", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/linear.svg" + }, + { + "id": "simple-icons:miro", + "subject": "Collaboration tool or service", + "productName": "Miro", + "brandSourceUrl": "https://miro.com", + "brandGuidelinesUrl": "https://miro.com", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/miro.svg" + }, + { + "id": "simple-icons:mongodb", + "subject": "Data tool or service", + "productName": "MongoDB", + "brandSourceUrl": "https://www.mongodb.com/pressroom", + "brandGuidelinesUrl": "https://www.mongodb.com/pressroom", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/mongodb.svg" + }, + { + "id": "simple-icons:mysql", + "subject": "Data tool or service", + "productName": "MySQL", + "brandSourceUrl": "https://www.mysql.com/about/legal/logos.html", + "brandGuidelinesUrl": "https://www.mysql.com/about/legal/logos.html", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/mysql.svg" + }, + { + "id": "simple-icons:netlify", + "subject": "Infrastructure tool or service", + "productName": "Netlify", + "brandSourceUrl": "https://www.netlify.com/press/", + "brandGuidelinesUrl": "https://www.netlify.com/press/", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/netlify.svg" + }, + { + "id": "simple-icons:newrelic", + "subject": "Observability tool or service", + "productName": "New Relic", + "brandSourceUrl": "https://newrelic.com/about/media-assets", + "brandGuidelinesUrl": "https://newrelic.com/about/media-assets#guidelines", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/newrelic.svg" + }, + { + "id": "simple-icons:nextdotjs", + "subject": "Development tool or service", + "productName": "Next.js", + "brandSourceUrl": "https://vercel.com/design/brands#next-js", + "brandGuidelinesUrl": "https://vercel.com/design/brands#next-js", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/nextdotjs.svg" + }, + { + "id": "simple-icons:nginx", + "subject": "Infrastructure tool or service", + "productName": "NGINX", + "brandSourceUrl": "https://www.nginx.com/press/", + "brandGuidelinesUrl": "https://www.nginx.com/press/", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/nginx.svg" + }, + { + "id": "simple-icons:nodedotjs", + "subject": "Development tool or service", + "productName": "Node.js", + "brandSourceUrl": "https://nodejs.org/en/about/branding", + "brandGuidelinesUrl": "https://nodejs.org/en/about/branding", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/nodedotjs.svg" + }, + { + "id": "simple-icons:notion", + "subject": "Collaboration tool or service", + "productName": "Notion", + "brandSourceUrl": "https://www.notion.so", + "brandGuidelinesUrl": "https://www.notion.so", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/notion.svg" + }, + { + "id": "simple-icons:npm", + "subject": "Development tool or service", + "productName": "npm", + "brandSourceUrl": "https://www.npmjs.com", + "brandGuidelinesUrl": "https://docs.npmjs.com/policies/logos-and-usage", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/npm.svg" + }, + { + "id": "simple-icons:okta", + "subject": "Identity tool or service", + "productName": "Okta", + "brandSourceUrl": "https://www.okta.com/press-room/media-assets/", + "brandGuidelinesUrl": "https://www.okta.com/terms-of-use-for-okta-content/", + "recommendedNodeKind": "external", + "category": "Identity", + "archivePath": "simple-icons-16.29.0/icons/okta.svg" + }, + { + "id": "simple-icons:opentofu", + "subject": "Infrastructure tool or service", + "productName": "OpenTofu", + "brandSourceUrl": "https://github.com/opentofu/brand-artifacts/blob/0d4d0d6050ca0ff06471400bc3249a64c145f659/symbol-only/transparent/SVG/on-light-mono.svg", + "brandGuidelinesUrl": "https://github.com/opentofu/brand-artifacts/blob/0d4d0d6050ca0ff06471400bc3249a64c145f659/symbol-only/transparent/SVG/on-light-mono.svg", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/opentofu.svg" + }, + { + "id": "simple-icons:pagerduty", + "subject": "Observability tool or service", + "productName": "PagerDuty", + "brandSourceUrl": "https://www.pagerduty.com/brand/", + "brandGuidelinesUrl": "https://www.pagerduty.com/brand/", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/pagerduty.svg" + }, + { + "id": "simple-icons:pnpm", + "subject": "Development tool or service", + "productName": "pnpm", + "brandSourceUrl": "https://pnpm.io/logos", + "brandGuidelinesUrl": "https://pnpm.io/logos", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/pnpm.svg" + }, + { + "id": "simple-icons:postgresql", + "subject": "Data tool or service", + "productName": "PostgreSQL", + "brandSourceUrl": "https://wiki.postgresql.org/wiki/Logo", + "brandGuidelinesUrl": "https://www.postgresql.org/about/policies/trademarks/", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/postgresql.svg" + }, + { + "id": "simple-icons:prometheus", + "subject": "Observability tool or service", + "productName": "Prometheus", + "brandSourceUrl": "https://prometheus.io", + "brandGuidelinesUrl": "https://prometheus.io", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/prometheus.svg" + }, + { + "id": "simple-icons:pulumi", + "subject": "Infrastructure tool or service", + "productName": "Pulumi", + "brandSourceUrl": "https://www.pulumi.com", + "brandGuidelinesUrl": "https://www.pulumi.com/brand/", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/pulumi.svg" + }, + { + "id": "simple-icons:python", + "subject": "Development tool or service", + "productName": "Python", + "brandSourceUrl": "https://www.python.org/community/logos/", + "brandGuidelinesUrl": "https://www.python.org/community/logos/", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/python.svg" + }, + { + "id": "simple-icons:rabbitmq", + "subject": "Data tool or service", + "productName": "RabbitMQ", + "brandSourceUrl": "https://www.rabbitmq.com", + "brandGuidelinesUrl": "https://www.rabbitmq.com/trademark-guidelines.html", + "recommendedNodeKind": "queue", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/rabbitmq.svg" + }, + { + "id": "simple-icons:react", + "subject": "Development tool or service", + "productName": "React", + "brandSourceUrl": "https://github.com/facebook/create-react-app/blob/282c03f9525fdf8061ffa1ec50dce89296d916bd/test/fixtures/relative-paths/src/logo.svg", + "brandGuidelinesUrl": "https://github.com/facebook/create-react-app/blob/282c03f9525fdf8061ffa1ec50dce89296d916bd/test/fixtures/relative-paths/src/logo.svg", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/react.svg" + }, + { + "id": "simple-icons:redis", + "subject": "Data tool or service", + "productName": "Redis", + "brandSourceUrl": "https://redis.io/brand-guidelines", + "brandGuidelinesUrl": "https://redis.io/brand-guidelines", + "recommendedNodeKind": "cache", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/redis.svg" + }, + { + "id": "simple-icons:rust", + "subject": "Development tool or service", + "productName": "Rust", + "brandSourceUrl": "https://www.rust-lang.org", + "brandGuidelinesUrl": "https://www.rust-lang.org/policies/media-guide", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/rust.svg" + }, + { + "id": "simple-icons:sentry", + "subject": "Observability tool or service", + "productName": "Sentry", + "brandSourceUrl": "https://sentry.io/branding/", + "brandGuidelinesUrl": "https://sentry.io/branding/", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/sentry.svg" + }, + { + "id": "simple-icons:snowflake", + "subject": "Data tool or service", + "productName": "Snowflake", + "brandSourceUrl": "https://www.snowflake.com/brand-guidelines/", + "brandGuidelinesUrl": "https://www.snowflake.com/brand-guidelines/", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/snowflake.svg" + }, + { + "id": "simple-icons:splunk", + "subject": "Observability tool or service", + "productName": "Splunk", + "brandSourceUrl": "https://www.splunk.com", + "brandGuidelinesUrl": "https://www.splunk.com", + "recommendedNodeKind": "service", + "category": "Observability", + "archivePath": "simple-icons-16.29.0/icons/splunk.svg" + }, + { + "id": "simple-icons:supabase", + "subject": "Data tool or service", + "productName": "Supabase", + "brandSourceUrl": "https://github.com/supabase/supabase/blob/4031a7549f5d46da7bc79c01d56be4177dc7c114/packages/common/assets/images/supabase-logo-wordmark--light.svg", + "brandGuidelinesUrl": "https://github.com/supabase/supabase/blob/4031a7549f5d46da7bc79c01d56be4177dc7c114/packages/common/assets/images/supabase-logo-wordmark--light.svg", + "recommendedNodeKind": "database", + "category": "Data", + "archivePath": "simple-icons-16.29.0/icons/supabase.svg" + }, + { + "id": "simple-icons:svelte", + "subject": "Development tool or service", + "productName": "Svelte", + "brandSourceUrl": "https://github.com/sveltejs/branding/blob/c4dfca6743572087a6aef0e109ffe3d95596e86a/svelte-logo.svg", + "brandGuidelinesUrl": "https://github.com/sveltejs/branding/blob/c4dfca6743572087a6aef0e109ffe3d95596e86a/svelte-logo.svg", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/svelte.svg" + }, + { + "id": "simple-icons:terraform", + "subject": "Infrastructure tool or service", + "productName": "Terraform", + "brandSourceUrl": "https://www.hashicorp.com/brand", + "brandGuidelinesUrl": "https://www.hashicorp.com/brand", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/terraform.svg" + }, + { + "id": "simple-icons:trello", + "subject": "Collaboration tool or service", + "productName": "Trello", + "brandSourceUrl": "https://atlassian.design/resources/logo-library", + "brandGuidelinesUrl": "https://atlassian.design/foundations/logos", + "recommendedNodeKind": "external", + "category": "Collaboration", + "archivePath": "simple-icons-16.29.0/icons/trello.svg" + }, + { + "id": "simple-icons:vercel", + "subject": "Infrastructure tool or service", + "productName": "Vercel", + "brandSourceUrl": "https://vercel.com/geist/brands", + "brandGuidelinesUrl": "https://vercel.com/geist/brands", + "recommendedNodeKind": "service", + "category": "Infrastructure", + "archivePath": "simple-icons-16.29.0/icons/vercel.svg" + }, + { + "id": "simple-icons:vite", + "subject": "Development tool or service", + "productName": "Vite", + "brandSourceUrl": "https://github.com/voidzero-dev/community-design-resources/blob/55902097229cf01cf2a4ceb376f992f5cf306756/brand-assets/vite/vite-icon-color-bracketless.svg", + "brandGuidelinesUrl": "https://github.com/voidzero-dev/community-design-resources/blob/55902097229cf01cf2a4ceb376f992f5cf306756/brand-assets/vite/vite-icon-color-bracketless.svg", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/vite.svg" + }, + { + "id": "simple-icons:vuedotjs", + "subject": "Development tool or service", + "productName": "Vue.js", + "brandSourceUrl": "https://github.com/vuejs/art/blob/a1c78b74569b70a25300925b4eacfefcc143b8f6/logo.svg", + "brandGuidelinesUrl": "https://github.com/vuejs/art/blob/a1c78b74569b70a25300925b4eacfefcc143b8f6/README.md", + "recommendedNodeKind": "service", + "category": "Development", + "archivePath": "simple-icons-16.29.0/icons/vuedotjs.svg" + } + ] +} diff --git a/docs/provider-icon-import.md b/docs/provider-icon-import.md index b77f6bd..3a41555 100644 --- a/docs/provider-icon-import.md +++ b/docs/provider-icon-import.md @@ -2,7 +2,7 @@ ## Boundary -`stack icons import` converts a provider's official local ZIP archive into a Stack provider pack. Stack does not download, proxy, mirror, upload, or bundle provider asset bytes. The user obtains the archive from the official source, reviews the linked terms, and confirms that review with `--accept-terms`. +`stack icons import` converts official local ZIP archives into a Stack provider pack. Stack does not download, proxy, mirror, upload, or bundle provider asset bytes. The user obtains every archive from the recorded source, reviews the linked provider and brand terms, and confirms that review with `--accept-terms`. The command rejects a changed archive rather than guessing new paths or terms. A new upstream release requires a reviewed code change that updates the source, complete archive SHA-256, entry allowlist, terms review, visual comparison, and fixtures. @@ -16,7 +16,7 @@ stack icons import aws ~/Downloads/aws-icons.zip \ -o .stack-icons/aws ``` -`PROVIDER` is `aws`, `gcp`, or `azure`. The output directory must not exist. A successful import creates: +`PROVIDER` is `aws`, `gcp`, `azure`, or `simple-icons`. The output directory must not exist. A successful import creates: ```text / @@ -28,6 +28,36 @@ stack icons import aws ~/Downloads/aws-icons.zip \ The manifest follows the public [`stack-sh/theme` provider-pack schema](https://github.com/stack-sh/theme/blob/main/PROVIDER_PACKS.md). It records the official source, archive and asset hashes, upstream paths, allowed output categories, transformations, official product names, terms URL, review date, and non-endorsement notice. +Google publishes the audited core-product and category icons as separate archives. Supply both local files explicitly: + +```sh +stack icons import gcp ~/Downloads/core-products-icons.zip \ + --source categories=~/Downloads/category-icons.zip \ + --accept-terms \ + -o .stack-icons/gcp +``` + +The additional source ID and both archive hashes are preserved in `manifest.json` and `NOTICE.md`. + +## Finding IDs + +Do not maintain a copied list of more than one thousand IDs in documentation. Search the versioned, asset-free catalog that ships with the CLI: + +```sh +# Provider counts and audited releases +stack icons list + +# Every AWS catalog entry +stack icons list aws + +# Match ID, product name, or category +stack icons list aws s3 +stack icons list azure database +stack icons list simple-icons collaboration +``` + +The tab-separated output has stable `ID`, `PRODUCT`, `CATEGORY`, and recommended `KIND` columns, so it can also be filtered or imported into another tool. Existing documented IDs remain stable when catalogs grow. + ## Rendering with a local pack Use the imported directory explicitly when a diagram contains a namespaced provider icon: @@ -45,27 +75,31 @@ stack render architecture.stack \ ## Audited sources -| Provider | Official source | Audited release | Complete archive SHA-256 | Terms and guidance | Imported IDs | -| --- | --- | --- | --- | --- | --- | -| AWS | [AWS Architecture Icons](https://aws.amazon.com/architecture/icons/) | `Icon-package_07312026` | `d2d166c453526471749d520e0db022c459abef759d2946cf2dd1d1c992dc6526` | [AWS Trademark Guidelines](https://aws.amazon.com/trademark-guidelines/) | `aws:s3`, `aws:sqs`, `aws:lambda`, `aws:ec2`, `aws:rds`, `aws:dynamodb`, `aws:eks` | -| Google Cloud | [Google Cloud Icon Library](https://cloud.google.com/icons) | Core product icons from the May 2026 guide | `6531a10f58bc599c24d9a455d81dd757c1a03c3c43da9cddf639b859c1c1eece` | [Google Brand Resource Center](https://about.google/brand-resource-center/) | `gcp:cloud-run`, `gcp:cloud-storage`, `gcp:compute-engine`, `gcp:gke`, `gcp:bigquery`, `gcp:cloud-sql` | -| Azure | [Azure Architecture Icons](https://learn.microsoft.com/azure/architecture/icons/) | `Azure_Public_Service_Icons_V24` | `921594ccd1bf3d9c0a1bd7b6d924e050551a59342f2b353bb74bdcf761c35141` | `Microsoft_Terms_of_Use.pdf` inside the official archive and the source page | `azure:virtual-machines`, `azure:storage-accounts`, `azure:azure-sql-database`, `azure:aks`, `azure:app-service` | +| Provider | Catalog | Official archive | Audited release | Complete archive SHA-256 | Terms and guidance | +| --- | ---: | --- | --- | --- | --- | +| AWS | 305 | [AWS Architecture Icons](https://aws.amazon.com/architecture/icons/) | `Icon-package_07312026` | `d2d166c453526471749d520e0db022c459abef759d2946cf2dd1d1c992dc6526` | [AWS Trademark Guidelines](https://aws.amazon.com/trademark-guidelines/) | +| Google Cloud core products | 19 | [Google Cloud Icon Library](https://cloud.google.com/icons) | May 2026 guide | `6531a10f58bc599c24d9a455d81dd757c1a03c3c43da9cddf639b859c1c1eece` | [Google Brand Resource Center](https://about.google/brand-resource-center/) | +| Google Cloud product categories | 26 | [Google Cloud Icon Library](https://cloud.google.com/icons) | May 2026 guide | `e5bc3abd3527dc2500e9bff7f15870783e2c764129c49b7cd4c1b4e105345002` | [Google Brand Resource Center](https://about.google/brand-resource-center/) | +| Azure | 639 | [Azure Architecture Icons](https://learn.microsoft.com/azure/architecture/icons/) | `Azure_Public_Service_Icons_V24` | `921594ccd1bf3d9c0a1bd7b6d924e050551a59342f2b353bb74bdcf761c35141` | `Microsoft_Terms_of_Use.pdf` inside the official archive and the source page | +| Curated tools | 62 | [Simple Icons 16.29.0](https://github.com/simple-icons/simple-icons/releases/tag/16.29.0) | `16.29.0` | `99f30fabd5be19dab51e09b2adebb6fe54fce1f3709ddfdc936a1338dfebc68d` | [Simple Icons disclaimer](https://github.com/simple-icons/simple-icons/blob/16.29.0/DISCLAIMER.md), plus the per-icon brand links in the catalog and generated notice | + +The AWS and Azure catalogs cover every canonical service SVG entry selected from the audited official archives. Byte-identical Azure aliases are deduplicated, while visually distinct same-name entries keep distinct stable IDs. Google Cloud includes all 19 core-product and all 26 category SVGs in the two audited archives. The curated tools set covers common source control, collaboration, design, infrastructure, data, identity, and observability products, including GitHub, GitHub Actions, GitLab, Bitbucket, Notion, Linear, Atlassian, Jira, Confluence, Trello, Discord, Figma, Miro, Docker, Kubernetes, Terraform, OpenTofu, Pulumi, Datadog, Grafana, and Sentry. -The Google Cloud category archive is separately audited but is not accepted by this first importer slice. In particular, `gcp:serverless` remains unavailable until the manifest contract can identify every source archive used by one pack. +Simple Icons makes its repository available under CC0, but its disclaimer explicitly separates that distribution license from rights in individual brand marks. The Stack catalog therefore records a source and guideline URL on every curated icon, and generated notices preserve those links. Inclusion is discoverability metadata, not an assertion that every use is permitted or endorsed. ## Security and artwork preservation The importer: - caps the complete archive at 32 MiB and each selected SVG at 1 MiB; -- verifies the complete ZIP before parsing and reads only exact allowlisted entry names; +- verifies every complete ZIP before parsing and reads only exact allowlisted entry names; - rejects directories, symbolic links, traversal paths, malformed XML, document types, entities, processing instructions, nested SVG, scripts, event handlers, foreign namespaces, visible text, external URLs, data URLs, and executable URLs; - accepts only a small SVG element and attribute allowlist; - converts the audited Google Cloud fill classes into equivalent presentation attributes; - removes comments, titles, unused identifiers, and non-rendering generator metadata; -- namespaces referenced Azure gradient IDs before embedding multiple icons in one document; +- namespaces referenced gradient IDs before embedding multiple icons in one document; - preserves view boxes, geometry, colors, gradient stops, and aspect ratios; - records original and processed hashes plus every visual-preservation transformation; - creates the complete pack in a temporary sibling directory and renames it into place without overwriting an existing path. -The audited 18 source/processed pairs were rasterized at 512 by 512 pixels and compared with zero changed pixels. Real provider archives and generated packs remain temporary local test inputs and are never committed. +Catalog metadata is validated for unique stable IDs and archive paths, exact source references, hashes, local-only processing, disabled redistribution targets, legacy ID compatibility, and required per-brand guidance. Real provider archives, source SVGs, and generated packs remain temporary local test inputs and are never committed. diff --git a/scripts/generate-provider-catalogs.mjs b/scripts/generate-provider-catalogs.mjs new file mode 100644 index 0000000..2f3df88 --- /dev/null +++ b/scripts/generate-provider-catalogs.mjs @@ -0,0 +1,507 @@ +import { createHash } from "node:crypto" +import { execFileSync } from "node:child_process" +import { mkdir, readFile, writeFile } from "node:fs/promises" +import path from "node:path" +import { fileURLToPath } from "node:url" + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..") +const argumentsByName = new Map() +for (let index = 2; index < process.argv.length; index += 2) { + const option = process.argv[index] + const value = process.argv[index + 1] + if (!option?.startsWith("--") || !value) { + throw new Error("Expected --aws, --gcp-core, --gcp-category, --azure, and --simple-icons paths") + } + argumentsByName.set(option.slice(2), path.resolve(value)) +} + +for (const name of ["aws", "gcp-core", "gcp-category", "azure", "simple-icons"]) { + if (!argumentsByName.has(name)) throw new Error(`Missing --${name}`) +} + +const archiveHashes = { + aws: "d2d166c453526471749d520e0db022c459abef759d2946cf2dd1d1c992dc6526", + "gcp-core": "6531a10f58bc599c24d9a455d81dd757c1a03c3c43da9cddf639b859c1c1eece", + "gcp-category": "e5bc3abd3527dc2500e9bff7f15870783e2c764129c49b7cd4c1b4e105345002", + azure: "921594ccd1bf3d9c0a1bd7b6d924e050551a59342f2b353bb74bdcf761c35141", + "simple-icons": "99f30fabd5be19dab51e09b2adebb6fe54fce1f3709ddfdc936a1338dfebc68d", +} + +for (const [name, expected] of Object.entries(archiveHashes)) { + const bytes = await readFile(argumentsByName.get(name)) + const actual = createHash("sha256").update(bytes).digest("hex") + if (actual !== expected) throw new Error(`${name} archive hash changed: ${actual}`) +} + +function entries(name) { + return execFileSync("zipinfo", ["-1", argumentsByName.get(name)], { + encoding: "utf8", + maxBuffer: 16 * 1024 * 1024, + }) + .trim() + .split("\n") +} + +function entryBytes(name, entry) { + return execFileSync("unzip", ["-p", argumentsByName.get(name), entry], { + maxBuffer: 16 * 1024 * 1024, + }) +} + +function slugify(value) { + return value + .normalize("NFKD") + .replace(/&/g, " and ") + .replace(/\+/g, " plus ") + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-|-$/g, "") + .replace(/-+/g, "-") +} + +function simpleIconSlug(value) { + return value + .normalize("NFKD") + .toLowerCase() + .replace(/\+/g, "plus") + .replace(/\./g, "dot") + .replace(/&/g, "and") + .replace(/[^a-z0-9]/g, "") +} + +function source({ + pageUrl, + archiveUrl, + archiveSha256, + release, + termsUrl, + copyright, + licenseId, + archiveLicenseIncluded, +}) { + return { + pageUrl, + archiveUrl, + archiveSha256: `sha256:${archiveSha256}`, + release, + retrievedAt: "2026-09-04", + termsUrl, + termsReviewedAt: "2026-09-04", + reviewAfter: "2026-12-03", + copyright, + licenseId, + archiveLicenseIncluded, + } +} + +function profile({ provider, source, additionalSources = [], rights, notice, icons }) { + return { + catalogVersion: "1.0", + packVersion: "0.2.0", + provider, + source, + additionalSources, + rights, + notice, + icons: icons.sort((left, right) => left.id.localeCompare(right.id)), + } +} + +function rights(permittedOutputs, productNameNearby = true) { + return { + termsAcceptanceRequired: true, + permittedOutputs, + redistribution: { + cargo: false, + npm: false, + wasm: false, + webAsset: false, + nativeBinary: false, + generatedOutput: true, + }, + processing: { + localOnly: true, + automaticDownload: false, + serverUpload: false, + preserveColors: true, + preserveGeometry: true, + productNameNearby, + }, + modificationPolicy: "visual-preservation-only", + } +} + +const awsIdOverrides = new Map([ + ["Amazon-Simple-Storage-Service", "s3"], + ["Amazon-Simple-Queue-Service", "sqs"], + ["AWS-Lambda", "lambda"], + ["Amazon-EC2", "ec2"], + ["Amazon-RDS", "rds"], + ["Amazon-DynamoDB", "dynamodb"], + ["Amazon-Elastic-Kubernetes-Service", "eks"], +]) +const awsProductOverrides = new Map([ + ["Amazon-Simple-Storage-Service", "Amazon Simple Storage Service (Amazon S3)"], + ["Amazon-Simple-Queue-Service", "Amazon Simple Queue Service (Amazon SQS)"], + ["Amazon-EC2", "Amazon Elastic Compute Cloud (Amazon EC2)"], + ["Amazon-RDS", "Amazon Relational Database Service (Amazon RDS)"], + ["Amazon-Elastic-Kubernetes-Service", "Amazon Elastic Kubernetes Service (Amazon EKS)"], +]) +function awsNodeKind(category, name) { + if (name === "AWS-Lambda") return "function" + if (name.includes("Queue") || name.includes("EventBridge")) return "queue" + if (category === "Databases") { + if (name.includes("ElastiCache") || name.includes("MemoryDB")) return "cache" + return "database" + } + if (category === "Storage" || category === "Cloud-Financial-Management") return "storage" + return "service" +} + +const awsRows = entries("aws") + .filter((entry) => /^Architecture-Service-Icons_[^/]+\/Arch_[^/]+\/48\/.*\.svg$/.test(entry)) + .map((archivePath) => { + const category = archivePath.match(/\/Arch_([^/]+)\/48\//)?.[1] ?? "Other" + const name = path.basename(archivePath).replace(/^Arch_/, "").replace(/_48\.svg$/, "") + return { archivePath, category, name, baseId: awsIdOverrides.get(name) ?? slugify(name) } + }) +const awsGroups = Map.groupBy(awsRows, (row) => row.baseId) +const awsIcons = [] +for (const [baseId, rows] of awsGroups) { + const ordered = rows.toSorted((left, right) => left.archivePath.localeCompare(right.archivePath)) + for (const [index, row] of ordered.entries()) { + const id = index === 0 ? baseId : `${baseId}-${slugify(row.category)}` + awsIcons.push({ + id: `aws:${id}`, + subject: `${row.category.replaceAll("-", " ")} product or service`, + productName: awsProductOverrides.get(row.name) ?? row.name.replaceAll("-", " "), + recommendedNodeKind: awsNodeKind(row.category, row.name), + category: row.category.replaceAll("-", " "), + archivePath: row.archivePath, + }) + } +} + +const gcpCoreIdOverrides = new Map([ + ["GKE", "gke"], + ["Cloud Storage", "cloud-storage"], + ["Compute Engine", "compute-engine"], + ["Cloud Run", "cloud-run"], + ["Cloud SQL", "cloud-sql"], +]) +function gcpNodeKind(name) { + if (/Storage|Hyperdisk/.test(name)) return "storage" + if (/BigQuery|Spanner|SQL|AlloyDB|Databases/.test(name)) return "database" + if (/Serverless/.test(name)) return "function" + if (/Agents/.test(name)) return "worker" + return "service" +} +const gcpCoreIcons = entries("gcp-core") + .filter((entry) => entry.endsWith(".svg")) + .map((archivePath) => { + const name = archivePath.split("/")[1] + return { + id: `gcp:${gcpCoreIdOverrides.get(name) ?? slugify(name)}`, + subject: "Google Cloud core product", + productName: name === "GKE" ? "Google Kubernetes Engine" : name, + recommendedNodeKind: gcpNodeKind(name), + category: "Core products", + archivePath, + } + }) +const gcpCategoryIcons = entries("gcp-category") + .filter((entry) => entry.endsWith(".svg")) + .map((archivePath) => { + const rawName = archivePath.split("/")[1] + const name = rawName.replace(" _ ", " & ") + const id = name === "Serverless Computing" ? "serverless" : slugify(name) + return { + id: `gcp:${id}`, + subject: "Google Cloud product category", + productName: `${name} category`, + recommendedNodeKind: gcpNodeKind(name), + category: "Product categories", + sourceId: "categories", + archivePath, + } + }) + +const azureIdOverrides = new Map([ + ["Virtual-Machine", "virtual-machines"], + ["Storage-Accounts", "storage-accounts"], + ["SQL-Database", "azure-sql-database"], + ["Kubernetes-Services", "aks"], + ["App-Services", "app-service"], +]) +const azureProductOverrides = new Map([ + ["Virtual-Machine", "Azure Virtual Machines"], + ["Storage-Accounts", "Azure Storage Accounts"], + ["SQL-Database", "Azure SQL Database"], + ["Kubernetes-Services", "Azure Kubernetes Service (AKS)"], + ["App-Services", "Azure App Service"], +]) +const azurePreferredPaths = new Map([ + ["aks", "Azure_Public_Service_Icons/Icons/containers/10023-icon-service-Kubernetes-Services.svg"], + ["app-service", "Azure_Public_Service_Icons/Icons/app services/10035-icon-service-App-Services.svg"], +]) +function azureNodeKind(category, name) { + if (category === "databases") return /Redis|Cache/.test(name) ? "cache" : "database" + if (category === "storage") return "storage" + if (/Function-Apps/.test(name)) return "function" + if (/Queue|Service-Bus|Event-Hub/.test(name)) return "queue" + return "service" +} +const azureRows = entries("azure") + .filter((entry) => entry.endsWith(".svg")) + .map((archivePath) => { + const fileName = path.basename(archivePath) + const numericId = fileName.match(/^(\d+)-icon-service-/)?.[1] ?? "unknown" + const name = fileName.replace(/^\d+-icon-service-/, "").replace(/\.svg$/, "") + const category = archivePath.split("/").at(-2) ?? "other" + return { + archivePath, + numericId, + name, + category, + baseId: azureIdOverrides.get(name) ?? slugify(name), + digest: createHash("sha256").update(entryBytes("azure", archivePath)).digest("hex"), + } + }) +const azureGroups = Map.groupBy(azureRows, (row) => row.baseId) +const azureIcons = [] +for (const [baseId, rows] of azureGroups) { + const preferredPath = azurePreferredPaths.get(baseId) + const ordered = rows.toSorted((left, right) => { + if (left.archivePath === preferredPath) return -1 + if (right.archivePath === preferredPath) return 1 + return left.archivePath.localeCompare(right.archivePath) + }) + const uniqueRows = [] + const seenDigests = new Set() + for (const row of ordered) { + if (!seenDigests.has(row.digest)) uniqueRows.push(row) + seenDigests.add(row.digest) + } + for (const [index, row] of uniqueRows.entries()) { + const id = index === 0 ? baseId : `${baseId}-${row.numericId}` + azureIcons.push({ + id: `azure:${id}`, + subject: `${row.category} product or service`, + productName: azureProductOverrides.get(row.name) ?? row.name.replaceAll("-", " "), + recommendedNodeKind: azureNodeKind(row.category, row.name), + category: row.category, + archivePath: row.archivePath, + }) + } +} + +const selectedSimpleIcons = [ + "1password", + "ansible", + "apacheairflow", + "apachekafka", + "argo", + "atlassian", + "auth0", + "bitbucket", + "bun", + "circleci", + "cloudflare", + "confluence", + "datadog", + "deno", + "discord", + "docker", + "elastic", + "figma", + "firebase", + "git", + "github", + "githubactions", + "gitlab", + "go", + "grafana", + "helm", + "jenkins", + "jira", + "kubernetes", + "linear", + "miro", + "mongodb", + "mysql", + "netlify", + "newrelic", + "nextdotjs", + "nginx", + "nodedotjs", + "notion", + "npm", + "okta", + "opentofu", + "pagerduty", + "pnpm", + "postgresql", + "prometheus", + "pulumi", + "python", + "rabbitmq", + "react", + "redis", + "rust", + "sentry", + "snowflake", + "splunk", + "supabase", + "svelte", + "terraform", + "trello", + "vercel", + "vite", + "vuedotjs", +] +const simpleEntries = entries("simple-icons") +const simpleRoot = simpleEntries[0] +const simpleMetadata = JSON.parse( + entryBytes("simple-icons", `${simpleRoot}data/simple-icons.json`).toString("utf8"), +) +const simpleMetadataBySlug = new Map(simpleMetadata.map((icon) => [simpleIconSlug(icon.title), icon])) +const simpleCategories = new Map([ + ...["1password", "atlassian", "bitbucket", "confluence", "discord", "figma", "github", "githubactions", "gitlab", "jira", "linear", "miro", "notion", "trello"].map((id) => [id, "Collaboration"]), + ...["ansible", "argo", "circleci", "cloudflare", "docker", "helm", "jenkins", "kubernetes", "netlify", "nginx", "opentofu", "pulumi", "terraform", "vercel"].map((id) => [id, "Infrastructure"]), + ...["datadog", "grafana", "newrelic", "pagerduty", "prometheus", "sentry", "splunk"].map((id) => [id, "Observability"]), + ...["apacheairflow", "apachekafka", "elastic", "firebase", "mongodb", "mysql", "postgresql", "rabbitmq", "redis", "snowflake", "supabase"].map((id) => [id, "Data"]), + ...["auth0", "okta"].map((id) => [id, "Identity"]), + ...["bun", "deno", "git", "go", "nextdotjs", "nodedotjs", "npm", "pnpm", "python", "react", "rust", "svelte", "vite", "vuedotjs"].map((id) => [id, "Development"]), +]) +function simpleNodeKind(slug, category) { + if (["mongodb", "mysql", "postgresql", "snowflake", "supabase", "firebase"].includes(slug)) { + return "database" + } + if (slug === "redis") return "cache" + if (["apachekafka", "rabbitmq"].includes(slug)) return "queue" + if (category === "Collaboration" || category === "Identity") return "external" + return "service" +} +const simpleIcons = selectedSimpleIcons.map((slug) => { + const metadata = simpleMetadataBySlug.get(slug) + const archivePath = `${simpleRoot}icons/${slug}.svg` + if (!metadata || !simpleEntries.includes(archivePath)) { + throw new Error(`Simple Icons metadata or asset missing for ${slug}`) + } + const category = simpleCategories.get(slug) + if (!category) throw new Error(`Simple Icons category missing for ${slug}`) + return { + id: `simple-icons:${slug}`, + subject: `${category} tool or service`, + productName: metadata.title, + brandSourceUrl: metadata.source, + brandGuidelinesUrl: metadata.guidelines ?? metadata.source, + recommendedNodeKind: simpleNodeKind(slug, category), + category, + archivePath, + } +}) + +const profiles = { + aws: profile({ + provider: { id: "aws", name: "Amazon Web Services" }, + source: source({ + pageUrl: "https://aws.amazon.com/architecture/icons/", + archiveUrl: "https://d1.awsstatic.com/onedam/marketing-channels/website/public/shared/architecture-icon-release/Icon-package_07312026.5846e92413caa21490223536cc97f1269e44fa92.zip", + archiveSha256: archiveHashes.aws, + release: "Icon-package_07312026", + termsUrl: "https://aws.amazon.com/trademark-guidelines/", + copyright: "Copyright Amazon Web Services, Inc. or its affiliates", + licenseId: "LicenseRef-AWS-Architecture-Icons-Terms", + archiveLicenseIncluded: false, + }), + rights: rights(["architecture-diagram", "whitepaper", "presentation", "data-sheet", "poster"]), + notice: { + attribution: "AWS architecture icons are owned by Amazon Web Services, Inc. or its affiliates.", + termsSummary: "Use is limited to the architecture-diagram materials described by the official AWS Architecture Icons page and applicable AWS trademark guidelines.", + nonEndorsement: "Amazon Web Services does not sponsor or endorse this diagram or Stack.", + }, + icons: awsIcons, + }), + gcp: profile({ + provider: { id: "gcp", name: "Google Cloud" }, + source: source({ + pageUrl: "https://cloud.google.com/icons", + archiveUrl: "https://services.google.com/fh/files/misc/core-products-icons.zip", + archiveSha256: archiveHashes["gcp-core"], + release: "Core product icons (May 2026 guide)", + termsUrl: "https://about.google/brand-resource-center/", + copyright: "Copyright Google LLC", + licenseId: "LicenseRef-Google-Cloud-Product-Icons-Terms", + archiveLicenseIncluded: false, + }), + additionalSources: [ + { + id: "categories", + ...source({ + pageUrl: "https://cloud.google.com/icons", + archiveUrl: "https://services.google.com/fh/files/misc/category-icons.zip", + archiveSha256: archiveHashes["gcp-category"], + release: "Product category icons (May 2026 guide)", + termsUrl: "https://about.google/brand-resource-center/", + copyright: "Copyright Google LLC", + licenseId: "LicenseRef-Google-Cloud-Product-Icons-Terms", + archiveLicenseIncluded: false, + }), + }, + ], + rights: rights(["architecture-diagram", "documentation"]), + notice: { + attribution: "Google Cloud product icons are owned by Google LLC.", + termsSummary: "Use is limited to diagrams and technical documentation described by the official Google Cloud Icon Library and applicable Google brand terms.", + nonEndorsement: "Google does not sponsor or endorse this diagram or Stack.", + }, + icons: [...gcpCoreIcons, ...gcpCategoryIcons], + }), + azure: profile({ + provider: { id: "azure", name: "Microsoft Azure" }, + source: source({ + pageUrl: "https://learn.microsoft.com/azure/architecture/icons/", + archiveUrl: "https://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V24.zip", + archiveSha256: archiveHashes.azure, + release: "Azure_Public_Service_Icons_V24", + termsUrl: "https://learn.microsoft.com/azure/architecture/icons/", + copyright: "Copyright Microsoft Corporation", + licenseId: "LicenseRef-Microsoft-Azure-Architecture-Icons-Terms", + archiveLicenseIncluded: true, + }), + rights: rights(["architecture-diagram", "training-material", "documentation"]), + notice: { + attribution: "Azure architecture icons are owned by Microsoft Corporation.", + termsSummary: "Use is limited to architecture diagrams, training materials, and documentation under the terms included in the official Azure icon archive.", + nonEndorsement: "Microsoft does not sponsor or endorse this diagram or Stack.", + }, + icons: azureIcons, + }), + "simple-icons": profile({ + provider: { id: "simple-icons", name: "Simple Icons (curated tools)" }, + source: source({ + pageUrl: "https://simpleicons.org/", + archiveUrl: "https://github.com/simple-icons/simple-icons/archive/refs/tags/16.29.0.zip", + archiveSha256: archiveHashes["simple-icons"], + release: "16.29.0", + termsUrl: "https://github.com/simple-icons/simple-icons/blob/16.29.0/DISCLAIMER.md", + copyright: "Simple Icons contributors and the respective trademark owners", + licenseId: "LicenseRef-Simple-Icons-CC0-and-Brand-Rights", + archiveLicenseIncluded: true, + }), + rights: rights(["architecture-diagram", "documentation", "presentation"]), + notice: { + attribution: "Glyphs are sourced from Simple Icons 16.29.0. Product names and marks belong to their respective owners.", + termsSummary: "Simple Icons is CC0, but that does not imply that every included brand icon is CC0. Review each icon's recorded brand source and guidelines before use.", + nonEndorsement: "Simple Icons and the named brands do not sponsor or endorse this diagram or Stack.", + }, + icons: simpleIcons, + }), +} + +await mkdir(path.join(repositoryRoot, "catalogs"), { recursive: true }) +for (const [name, value] of Object.entries(profiles)) { + await writeFile(path.join(repositoryRoot, "catalogs", `${name}.json`), `${JSON.stringify(value, null, 2)}\n`) + console.log(`generated ${name}: ${value.icons.length} icons`) +} diff --git a/scripts/validate-provider-catalogs.mjs b/scripts/validate-provider-catalogs.mjs new file mode 100644 index 0000000..8430e43 --- /dev/null +++ b/scripts/validate-provider-catalogs.mjs @@ -0,0 +1,117 @@ +import { readFile, readdir } from "node:fs/promises" +import path from "node:path" +import { fileURLToPath } from "node:url" + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..") +const expectedCounts = new Map([ + ["aws", 305], + ["gcp", 45], + ["azure", 639], + ["simple-icons", 62], +]) +const requiredLegacyIds = [ + "aws:s3", + "aws:sqs", + "aws:lambda", + "aws:ec2", + "aws:rds", + "aws:dynamodb", + "aws:eks", + "gcp:cloud-run", + "gcp:cloud-storage", + "gcp:compute-engine", + "gcp:gke", + "gcp:bigquery", + "gcp:cloud-sql", + "gcp:serverless", + "azure:virtual-machines", + "azure:storage-accounts", + "azure:azure-sql-database", + "azure:aks", + "azure:app-service", +] +const requiredToolIds = [ + "simple-icons:github", + "simple-icons:githubactions", + "simple-icons:notion", + "simple-icons:linear", + "simple-icons:atlassian", + "simple-icons:jira", + "simple-icons:confluence", + "simple-icons:trello", + "simple-icons:figma", + "simple-icons:docker", + "simple-icons:kubernetes", + "simple-icons:terraform", +] + +function assert(condition, message) { + if (!condition) throw new Error(message) +} + +function validateSource(source, label) { + assert(typeof source?.pageUrl === "string" && source.pageUrl.startsWith("https://"), `${label}: invalid pageUrl`) + assert(typeof source?.archiveUrl === "string" && source.archiveUrl.startsWith("https://"), `${label}: invalid archiveUrl`) + assert(/^sha256:[0-9a-f]{64}$/.test(source?.archiveSha256), `${label}: invalid archiveSha256`) + assert(typeof source?.release === "string" && source.release.length > 0, `${label}: missing release`) + assert(typeof source?.termsUrl === "string" && source.termsUrl.startsWith("https://"), `${label}: invalid termsUrl`) +} + +const files = (await readdir(path.join(repositoryRoot, "catalogs"))) + .filter((name) => name.endsWith(".json")) + .sort() +assert(files.length === expectedCounts.size, `expected ${expectedCounts.size} catalogs, found ${files.length}`) + +const allIds = new Set() +for (const file of files) { + const catalog = JSON.parse(await readFile(path.join(repositoryRoot, "catalogs", file), "utf8")) + const providerId = catalog.provider?.id + assert(expectedCounts.has(providerId), `${file}: unexpected provider ${providerId}`) + assert(file === `${providerId}.json`, `${file}: file name does not match provider ID`) + assert(catalog.catalogVersion === "1.0", `${file}: unsupported catalogVersion`) + assert(catalog.icons?.length === expectedCounts.get(providerId), `${file}: unexpected icon count`) + validateSource(catalog.source, `${file}:primary`) + + const sourceIds = new Set(["primary"]) + for (const additional of catalog.additionalSources ?? []) { + assert(/^[a-z][a-z0-9-]*$/.test(additional.id), `${file}: invalid additional source ID`) + assert(!sourceIds.has(additional.id), `${file}: duplicate source ID ${additional.id}`) + sourceIds.add(additional.id) + validateSource(additional, `${file}:${additional.id}`) + } + + const rights = catalog.rights + assert(rights?.termsAcceptanceRequired === true, `${file}: terms acceptance must be required`) + assert(rights?.processing?.localOnly === true, `${file}: imports must stay local`) + assert(rights?.processing?.automaticDownload === false, `${file}: automatic download must be disabled`) + assert(rights?.processing?.serverUpload === false, `${file}: server upload must be disabled`) + for (const target of ["cargo", "npm", "wasm", "webAsset", "nativeBinary"]) { + assert(rights?.redistribution?.[target] === false, `${file}: ${target} redistribution must be disabled`) + } + + const archivePaths = new Set() + for (const icon of catalog.icons) { + assert(new RegExp(`^${providerId}:[a-z0-9]+(?:-[a-z0-9]+)*$`).test(icon.id), `${file}: invalid icon ID ${icon.id}`) + assert(!allIds.has(icon.id), `${file}: duplicate icon ID ${icon.id}`) + allIds.add(icon.id) + assert(typeof icon.productName === "string" && icon.productName.length > 0, `${icon.id}: missing productName`) + assert(typeof icon.category === "string" && icon.category.length > 0, `${icon.id}: missing category`) + assert(typeof icon.archivePath === "string" && icon.archivePath.endsWith(".svg"), `${icon.id}: invalid archivePath`) + const pathKey = `${icon.sourceId ?? "primary"}:${icon.archivePath}` + assert(!archivePaths.has(pathKey), `${icon.id}: duplicate archive path ${pathKey}`) + archivePaths.add(pathKey) + assert(sourceIds.has(icon.sourceId ?? "primary"), `${icon.id}: unknown source ID`) + assert(!JSON.stringify(icon).includes(", + arguments: &mut dyn Iterator, stdout: &mut dyn Write, stderr: &mut dyn Write, ) -> u8 { @@ -115,6 +118,9 @@ fn run_icons( } return write_stdout(ICONS_HELP, stdout, stderr); } + if command == OsStr::new("list") { + return run_icons_list(arguments, stdout, stderr); + } if command != OsStr::new("import") { return argument_error( &format!( @@ -127,8 +133,41 @@ fn run_icons( run_icons_import(arguments, stdout, stderr) } +fn run_icons_list( + arguments: &mut dyn Iterator, + stdout: &mut dyn Write, + stderr: &mut dyn Write, +) -> u8 { + let first = arguments.next(); + if first + .as_ref() + .is_some_and(|value| value == OsStr::new("--help") || value == OsStr::new("-h")) + { + if let Some(extra) = arguments.next() { + return argument_error( + &format!("unexpected argument '{}'", extra.to_string_lossy()), + stderr, + ); + } + return write_stdout(ICONS_LIST_HELP, stdout, stderr); + } + let query = arguments.next(); + if let Some(extra) = arguments.next() { + return argument_error( + &format!("unexpected argument '{}'", extra.to_string_lossy()), + stderr, + ); + } + let provider = first.as_ref().map(|value| value.to_string_lossy()); + let query = query.as_ref().map(|value| value.to_string_lossy()); + match provider::render_catalog_list(provider.as_deref(), query.as_deref()) { + Ok(output) => write_stdout(&output, stdout, stderr), + Err(error) => write_stderr_error(&format!("cannot list provider icons: {error}"), stderr), + } +} + fn run_icons_import( - mut arguments: impl Iterator, + arguments: &mut dyn Iterator, stdout: &mut dyn Write, stderr: &mut dyn Write, ) -> u8 { @@ -162,6 +201,7 @@ fn run_icons_import( let mut accepted_terms = false; let mut output = None; + let mut additional_sources = BTreeMap::new(); while let Some(option) = arguments.next() { if option == OsStr::new("--accept-terms") { if accepted_terms { @@ -176,6 +216,25 @@ fn run_icons_import( return argument_error("missing output directory after '-o'", stderr); }; output = Some(PathBuf::from(path)); + } else if option == OsStr::new("--source") { + let Some(value) = arguments.next() else { + return argument_error("missing = after '--source'", stderr); + }; + let Some(value) = value.to_str() else { + return argument_error("source ID and archive must be valid UTF-8", stderr); + }; + let Some((id, path)) = value.split_once('=') else { + return argument_error("source must use =", stderr); + }; + if id.is_empty() || path.is_empty() { + return argument_error("source must use non-empty =", stderr); + } + if additional_sources + .insert(id.to_owned(), PathBuf::from(path)) + .is_some() + { + return argument_error(&format!("duplicate source ID '{id}'"), stderr); + } } else { return argument_error( &format!("unexpected argument '{}'", option.to_string_lossy()), @@ -195,8 +254,19 @@ fn run_icons_import( if output == Path::new(&archive) { return argument_error("archive and output directory must be different", stderr); } + if additional_sources.values().any(|path| path == &output) { + return argument_error( + "source archive and output directory must be different", + stderr, + ); + } let provider_name = provider.to_string_lossy(); - match provider::import_provider_pack(&provider_name, Path::new(&archive), &output) { + match provider::import_provider_pack( + &provider_name, + Path::new(&archive), + &additional_sources, + &output, + ) { Ok(summary) => write_stdout( &format!( "Imported {} {} icons to '{}'.\nManifest: {}\nNotice: {}\n", @@ -613,25 +683,41 @@ fn render_provider_notices(notices: &[ProviderNotice]) -> String { for notice in notices { let _ = write!( output, - "\n## {} (`{}`)\n\n- Pack version: {}\n- Pack revision: `{}`\n- Source release: {}\n- Archive SHA-256: `{}`\n- Terms URL: {}\n\n{}\n\n{}\n\n{}\n\nUsed icons:\n", + "\n## {} (`{}`)\n\n- Pack version: {}\n- Pack revision: `{}`\n\n{}\n\n{}\n\n{}\n\nSources:\n", notice_text(¬ice.provider_name), notice.provider_id, notice_text(¬ice.pack_version), notice.pack_revision, - notice_text(¬ice.source_release), - notice.archive_sha256, - notice_text(¬ice.terms_url), notice_text(¬ice.attribution), notice_text(¬ice.terms_summary), notice_text(¬ice.non_endorsement), ); - for icon in ¬ice.icons { + for source in ¬ice.sources { let _ = writeln!( output, - "- `{}`: {}", + "- `{}`: release {}; archive `{}`; terms {}", + source.id, + notice_text(&source.release), + source.archive_sha256, + notice_text(&source.terms_url), + ); + } + output.push_str("\nUsed icons:\n"); + for icon in ¬ice.icons { + let _ = write!( + output, + "- `{}`: {} (source `{}`)", icon.id, - notice_text(&icon.product_name) + notice_text(&icon.product_name), + notice_text(&icon.source_id), ); + if let Some(url) = &icon.brand_source_url { + let _ = write!(output, "; brand source {}", notice_text(url)); + } + if let Some(url) = &icon.brand_guidelines_url { + let _ = write!(output, "; brand guidelines {}", notice_text(url)); + } + output.push('\n'); } } output @@ -961,7 +1047,7 @@ mod tests { run_without_input([OsString::from("--version")], &mut stdout, &mut stderr), EXIT_SUCCESS ); - assert_eq!(stdout, b"stack 0.1.0\n"); + assert_eq!(stdout, b"stack 0.2.0\n"); assert!(stderr.is_empty()); stdout.clear(); @@ -1088,6 +1174,13 @@ mod tests { ], vec![OsString::from("icons")], vec![OsString::from("icons"), OsString::from("unknown")], + vec![ + OsString::from("icons"), + OsString::from("list"), + OsString::from("aws"), + OsString::from("s3"), + OsString::from("extra"), + ], vec![ OsString::from("icons"), OsString::from("--help"), @@ -1120,6 +1213,17 @@ mod tests { OsString::from("import"), OsString::from("--unknown"), ], + vec![ + OsString::from("icons"), + OsString::from("import"), + OsString::from("gcp"), + OsString::from("core.zip"), + OsString::from("--source"), + OsString::from("invalid"), + OsString::from("--accept-terms"), + OsString::from("-o"), + OsString::from("pack"), + ], vec![ OsString::from("check"), OsString::from("file.stack"), @@ -1209,6 +1313,58 @@ mod tests { EXIT_SUCCESS ); assert_eq!(stdout, ICONS_IMPORT_HELP.as_bytes()); + + stdout.clear(); + assert_eq!( + run_without_input( + [ + OsString::from("icons"), + OsString::from("list"), + OsString::from("--help"), + ], + &mut stdout, + &mut stderr, + ), + EXIT_SUCCESS + ); + assert_eq!(stdout, ICONS_LIST_HELP.as_bytes()); + } + + #[test] + fn provider_catalog_listing_is_searchable_without_asset_bytes() { + let mut stdout = Vec::new(); + let mut stderr = Vec::new(); + assert_eq!( + run_without_input( + [OsString::from("icons"), OsString::from("list")], + &mut stdout, + &mut stderr, + ), + EXIT_SUCCESS + ); + let listing = String::from_utf8_lossy(&stdout); + assert!(listing.contains("aws\t305")); + assert!(listing.contains("azure\t639")); + assert!(listing.contains("simple-icons\t62")); + + stdout.clear(); + assert_eq!( + run_without_input( + [ + OsString::from("icons"), + OsString::from("list"), + OsString::from("aws"), + OsString::from("s3"), + ], + &mut stdout, + &mut stderr, + ), + EXIT_SUCCESS + ); + let listing = String::from_utf8_lossy(&stdout); + assert!(listing.contains("aws:s3\tAmazon Simple Storage Service")); + assert!(listing.lines().count() >= 2); + assert!(stderr.is_empty()); } #[test] diff --git a/src/provider.rs b/src/provider.rs index 959352c..7fa7aeb 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -1,7 +1,7 @@ //! Local-only provider icon archive import. use std::collections::{BTreeMap, BTreeSet}; -use std::fmt; +use std::fmt::{self, Write as _}; use std::fs::{self, OpenOptions}; use std::io::{Cursor, Read, Write}; use std::path::{Path, PathBuf}; @@ -10,25 +10,28 @@ use roxmltree::{Document, Node, NodeType}; use sha2::{Digest, Sha256}; use stack_theme::{ ProviderIcon, ProviderIconAsset, ProviderNodeKind, ProviderPack, ProviderPackDistributionMode, - ProviderPackIdentity, ProviderPackModificationPolicy, ProviderPackNotice, - ProviderPackPermittedOutput, ProviderPackProcessing, ProviderPackRedistribution, - ProviderPackRights, ProviderPackSource, ProviderPackTransformation, + ProviderPackSource, ProviderPackTransformation, }; use zip::ZipArchive; +use crate::provider_catalog::{ProviderCatalog, provider_catalog, provider_catalogs}; + const PROVIDER_PACK_SCHEMA: &str = "https://raw.githubusercontent.com/stack-sh/theme/main/schemas/provider-pack.schema.json"; const MAX_ARCHIVE_BYTES: u64 = 32 * 1024 * 1024; const MAX_ICON_BYTES: u64 = 1024 * 1024; const SVG_NAMESPACE: &str = "http://www.w3.org/2000/svg"; +const XLINK_NAMESPACE: &str = "http://www.w3.org/1999/xlink"; const ALLOWED_ELEMENTS: &[&str] = &[ "circle", + "clipPath", "defs", "ellipse", "g", "line", "linearGradient", + "mask", "path", "polygon", "polyline", @@ -40,16 +43,24 @@ const ALLOWED_ELEMENTS: &[&str] = &[ const ALLOWED_ATTRIBUTES: &[&str] = &[ "aria-hidden", + "clip-path", "clip-rule", "cx", "cy", "d", "fill", + "fill-opacity", "fill-rule", + "fx", + "fy", "gradientTransform", "gradientUnits", "height", + "href", "id", + "isolation", + "mask", + "maskUnits", "opacity", "offset", "points", @@ -62,6 +73,7 @@ const ALLOWED_ATTRIBUTES: &[&str] = &[ "stroke", "stroke-linecap", "stroke-linejoin", + "stroke-miterlimit", "stroke-width", "transform", "viewBox", @@ -74,38 +86,6 @@ const ALLOWED_ATTRIBUTES: &[&str] = &[ "y2", ]; -#[derive(Clone, Copy)] -struct IconProfile<'a> { - slug: &'a str, - subject: &'a str, - product_name: &'a str, - node_kind: ProviderNodeKind, - archive_path: &'a str, -} - -#[derive(Clone, Copy)] -struct ProviderProfile<'a> { - id: &'a str, - name: &'a str, - page_url: &'a str, - archive_url: &'a str, - archive_sha256: &'a str, - release: &'a str, - retrieved_at: &'a str, - terms_url: &'a str, - terms_reviewed_at: &'a str, - review_after: &'a str, - copyright: &'a str, - license_id: &'a str, - archive_license_included: bool, - permitted_outputs: &'a [ProviderPackPermittedOutput], - product_name_nearby: bool, - attribution: &'a str, - terms_summary: &'a str, - non_endorsement: &'a str, - icons: &'a [IconProfile<'a>], -} - /// Summary of one completed local provider-pack import. #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct ImportSummary { @@ -143,26 +123,26 @@ struct ProcessedIcon { transformations: Vec, } +struct ParsedViewBox { + integers: [i32; 4], + coordinate_scale: i32, +} + /// Imports one audited official archive into a new local pack directory. pub(crate) fn import_provider_pack( provider: &str, archive_path: &Path, + additional_archive_paths: &BTreeMap, output_path: &Path, ) -> Result { - let profile = match provider_profile(provider) { - Some(profile) => profile, - None => { - return Err(ImportError::new(format!( - "unknown provider '{provider}'; expected aws, gcp, or azure" - ))); - } - }; - import_profile(profile, archive_path, output_path) + let profile = provider_catalog(provider).map_err(ImportError::new)?; + import_profile(profile, archive_path, additional_archive_paths, output_path) } fn import_profile( - profile: ProviderProfile<'_>, + profile: ProviderCatalog, archive_path: &Path, + additional_archive_paths: &BTreeMap, output_path: &Path, ) -> Result { if output_path.exists() { @@ -171,67 +151,82 @@ fn import_profile( output_path.display() ))); } - let metadata = match fs::metadata(archive_path) { - Ok(metadata) => metadata, - Err(error) => { - return Err(ImportError::new(format!( - "cannot read archive '{}': {}", - archive_path.display(), - stable_io_error(error.kind()) - ))); - } - }; - if !metadata.is_file() { - return Err(ImportError::new(format!( - "archive '{}' is not a file", - archive_path.display() - ))); - } - if metadata.len() > MAX_ARCHIVE_BYTES { + let expected_additional = profile + .additional_sources + .iter() + .map(|source| source.id.as_str()) + .collect::>(); + if let Some(unexpected) = additional_archive_paths + .keys() + .find(|id| !expected_additional.contains(id.as_str())) + { return Err(ImportError::new(format!( - "archive '{}' exceeds the 32 MiB limit", - archive_path.display() + "provider '{}' does not declare an additional source '{unexpected}'", + profile.provider.id ))); } - let archive_bytes = match fs::read(archive_path) { - Ok(bytes) => bytes, - Err(error) => { - return Err(ImportError::new(format!( - "cannot read archive '{}': {}", - archive_path.display(), - stable_io_error(error.kind()) - ))); - } - }; - let archive_digest = sha256(&archive_bytes); - if archive_digest != profile.archive_sha256 { + if let Some(missing) = expected_additional + .iter() + .find(|id| !additional_archive_paths.contains_key(**id)) + { return Err(ImportError::new(format!( - "archive hash does not match the audited {} release; expected {}, received {}", - profile.release, profile.archive_sha256, archive_digest + "missing local archive for additional source '{missing}'" ))); } - let mut archive = match ZipArchive::new(Cursor::new(archive_bytes)) { - Ok(archive) => archive, - Err(_) => return Err(ImportError::new("archive is not a supported ZIP file")), - }; + let mut archives = BTreeMap::new(); + archives.insert( + "primary".to_owned(), + open_archive(archive_path, &profile.source)?, + ); + for additional in &profile.additional_sources { + let Some(path) = additional_archive_paths.get(&additional.id) else { + return Err(ImportError::new("missing additional provider archive")); + }; + archives.insert( + additional.id.clone(), + open_archive(path, &additional.source)?, + ); + } let mut manifest_icons = Vec::with_capacity(profile.icons.len()); let mut processed_assets = Vec::with_capacity(profile.icons.len()); - for icon in profile.icons { - let original = read_icon_entry(&mut archive, icon.archive_path)?; + for icon in &profile.icons { + let source_id = icon.source_id.as_deref().unwrap_or("primary"); + let Some(archive) = archives.get_mut(source_id) else { + return Err(ImportError::new(format!( + "icon '{}' references unknown source '{source_id}'", + icon.id + ))); + }; + let original = read_icon_entry(archive, &icon.archive_path)?; let original_sha256 = sha256(&original); - let processed = sanitize_svg(&original, profile.id, icon.slug)?; + let slug = icon + .id + .split_once(':') + .map(|(_, slug)| slug) + .ok_or_else(|| { + ImportError::new(format!("catalog icon '{}' is not namespaced", icon.id)) + })?; + let processed = sanitize_svg(&original, &profile.provider.id, slug).map_err(|error| { + ImportError::new(format!( + "cannot process catalog icon '{}': {error}", + icon.id + )) + })?; let processed_sha256 = sha256(processed.svg.as_bytes()); - let asset_path = format!("assets/{}.svg", icon.slug); + let asset_path = format!("assets/{slug}.svg"); manifest_icons.push(ProviderIcon { - id: format!("{}:{}", profile.id, icon.slug), - subject: icon.subject.to_owned(), - product_name: icon.product_name.to_owned(), - recommended_node_kind: icon.node_kind, + id: icon.id.clone(), + subject: icon.subject.clone(), + product_name: icon.product_name.clone(), + brand_source_url: icon.brand_source_url.clone(), + brand_guidelines_url: icon.brand_guidelines_url.clone(), + recommended_node_kind: icon.recommended_node_kind, asset: ProviderIconAsset { + source_id: icon.source_id.clone(), path: asset_path.clone(), - original_path: icon.archive_path.to_owned(), + original_path: icon.archive_path.clone(), view_box: processed.view_box, original_sha256, processed_sha256, @@ -241,56 +236,26 @@ fn import_profile( processed_assets.push((asset_path, processed.svg)); } - let manifest = ProviderPack { - schema: PROVIDER_PACK_SCHEMA.to_owned(), - schema_version: "1.0".to_owned(), - pack_version: "0.1.0".to_owned(), - provider: ProviderPackIdentity { - id: profile.id.to_owned(), - name: profile.name.to_owned(), - }, - distribution_mode: ProviderPackDistributionMode::UserImported, - source: ProviderPackSource { - page_url: profile.page_url.to_owned(), - archive_url: profile.archive_url.to_owned(), - archive_sha256: profile.archive_sha256.to_owned(), - release: profile.release.to_owned(), - retrieved_at: profile.retrieved_at.to_owned(), - terms_url: profile.terms_url.to_owned(), - terms_reviewed_at: profile.terms_reviewed_at.to_owned(), - review_after: profile.review_after.to_owned(), - copyright: profile.copyright.to_owned(), - license_id: profile.license_id.to_owned(), - archive_license_included: profile.archive_license_included, - }, - rights: ProviderPackRights { - terms_acceptance_required: true, - permitted_outputs: profile.permitted_outputs.to_vec(), - redistribution: ProviderPackRedistribution { - cargo: false, - npm: false, - wasm: false, - web_asset: false, - native_binary: false, - generated_output: true, - }, - processing: ProviderPackProcessing { - local_only: true, - automatic_download: false, - server_upload: false, - preserve_colors: true, - preserve_geometry: true, - product_name_nearby: profile.product_name_nearby, + let manifest = + ProviderPack { + schema: PROVIDER_PACK_SCHEMA.to_owned(), + schema_version: if profile.additional_sources.is_empty() + && profile.icons.iter().all(|icon| { + icon.brand_source_url.is_none() && icon.brand_guidelines_url.is_none() + }) { + "1.0".to_owned() + } else { + "1.1".to_owned() }, - modification_policy: ProviderPackModificationPolicy::VisualPreservationOnly, - }, - notice: ProviderPackNotice { - attribution: profile.attribution.to_owned(), - terms_summary: profile.terms_summary.to_owned(), - non_endorsement: profile.non_endorsement.to_owned(), - }, - icons: manifest_icons, - }; + pack_version: profile.pack_version.clone(), + provider: profile.provider.clone(), + distribution_mode: ProviderPackDistributionMode::UserImported, + source: profile.source.clone(), + additional_sources: profile.additional_sources.clone(), + rights: profile.rights.clone(), + notice: profile.notice.clone(), + icons: manifest_icons, + }; let mut manifest_bytes = match serde_json::to_vec_pretty(&manifest) { Ok(bytes) => bytes, Err(_) => return Err(ImportError::new("cannot serialize provider manifest")), @@ -329,13 +294,115 @@ fn import_profile( } Ok(ImportSummary { - provider_name: profile.name.to_owned(), + provider_name: profile.provider.name, icon_count: manifest.icons.len(), manifest_path: output_path.join("manifest.json"), notice_path: output_path.join("NOTICE.md"), }) } +fn open_archive( + archive_path: &Path, + source: &ProviderPackSource, +) -> Result>>, ImportError> { + let metadata = match fs::metadata(archive_path) { + Ok(metadata) => metadata, + Err(error) => { + return Err(ImportError::new(format!( + "cannot read archive '{}': {}", + archive_path.display(), + stable_io_error(error.kind()) + ))); + } + }; + if !metadata.is_file() { + return Err(ImportError::new(format!( + "archive '{}' is not a file", + archive_path.display() + ))); + } + if metadata.len() > MAX_ARCHIVE_BYTES { + return Err(ImportError::new(format!( + "archive '{}' exceeds the 32 MiB limit", + archive_path.display() + ))); + } + let archive_bytes = match fs::read(archive_path) { + Ok(bytes) => bytes, + Err(error) => { + return Err(ImportError::new(format!( + "cannot read archive '{}': {}", + archive_path.display(), + stable_io_error(error.kind()) + ))); + } + }; + let archive_digest = sha256(&archive_bytes); + if archive_digest != source.archive_sha256 { + return Err(ImportError::new(format!( + "archive hash does not match the audited {} release; expected {}, received {}", + source.release, source.archive_sha256, archive_digest + ))); + } + ZipArchive::new(Cursor::new(archive_bytes)) + .map_err(|_| ImportError::new("archive is not a supported ZIP file")) +} + +pub(crate) fn render_catalog_list( + provider: Option<&str>, + query: Option<&str>, +) -> Result { + if provider.is_none() { + let catalogs = provider_catalogs().map_err(ImportError::new)?; + let mut output = String::from("PROVIDER\tICONS\tRELEASE\n"); + for catalog in catalogs { + let _ = writeln!( + output, + "{}\t{}\t{}", + catalog.provider.id, + catalog.icons.len(), + catalog.source.release + ); + } + return Ok(output); + } + + let catalog = provider_catalog(provider.unwrap_or_default()).map_err(ImportError::new)?; + let query = query.unwrap_or_default().to_lowercase(); + let mut output = String::from("ID\tPRODUCT\tCATEGORY\tKIND\n"); + for icon in catalog.icons.iter().filter(|icon| { + query.is_empty() + || icon.id.to_lowercase().contains(&query) + || icon.product_name.to_lowercase().contains(&query) + || icon.category.to_lowercase().contains(&query) + }) { + let _ = writeln!( + output, + "{}\t{}\t{}\t{}", + icon.id, + icon.product_name, + icon.category, + node_kind_name(icon.recommended_node_kind) + ); + } + Ok(output) +} + +fn node_kind_name(kind: ProviderNodeKind) -> &'static str { + match kind { + ProviderNodeKind::Actor => "actor", + ProviderNodeKind::Client => "client", + ProviderNodeKind::Service => "service", + ProviderNodeKind::Function => "function", + ProviderNodeKind::Worker => "worker", + ProviderNodeKind::Database => "database", + ProviderNodeKind::Cache => "cache", + ProviderNodeKind::Queue => "queue", + ProviderNodeKind::Storage => "storage", + ProviderNodeKind::External => "external", + } +} + fn read_icon_entry( archive: &mut ZipArchive, entry_path: &str, @@ -407,13 +474,17 @@ fn sanitize_svg( "provider icon root must use the canonical SVG namespace", )); } - let view_box_value = match root.attribute("viewBox") { + let view_box_value = match root + .attribute("viewBox") + .or_else(|| root.attribute("xviewBox")) + { Some(value) => value, None => return Err(ImportError::new("provider icon is missing viewBox")), }; let view_box = parse_view_box(view_box_value)?; let styles = collect_styles(&document)?; - let (identifier_map, unused_identifiers) = identifier_map(&document, provider_id, icon_slug)?; + let (identifier_map, unused_identifiers) = + identifier_map(&document, &styles, provider_id, icon_slug)?; let mut removed_metadata = false; for node in document.descendants() { if matches!(node.node_type(), NodeType::Comment | NodeType::PI) @@ -429,6 +500,8 @@ fn sanitize_svg( removed_metadata, inlined_styles: !styles.is_empty(), removed_unused_identifiers: unused_identifiers, + view_box: view_box.integers, + coordinate_scale: view_box.coordinate_scale, }; let svg = match serialize_element(root, true, None, &mut state)? { Some(svg) => svg, @@ -451,11 +524,14 @@ fn sanitize_svg( if !identifier_map.is_empty() { transformations.push(ProviderPackTransformation::NamespaceIdentifiers); } + if view_box.coordinate_scale != 1 { + transformations.push(ProviderPackTransformation::ScaleViewBoxToIntegers); + } transformations.push(ProviderPackTransformation::NormalizeXml); Ok(ProcessedIcon { svg: format!("{svg}\n"), - view_box, + view_box: view_box.integers, transformations, }) } @@ -479,29 +555,87 @@ fn strip_xml_declaration(source: &str) -> Result<&str, ImportError> { Ok(trimmed[end + 2..].trim_start()) } -fn parse_view_box(value: &str) -> Result<[i32; 4], ImportError> { - let mut values = Vec::with_capacity(4); - for component in - value.split(|character: char| character.is_ascii_whitespace() || character == ',') - { - if component.is_empty() { - continue; - } - match component.parse::() { - Ok(component) => values.push(component), - Err(_) => { - return Err(ImportError::new( - "provider icon viewBox must contain four integers", - )); - } - } +fn parse_view_box(value: &str) -> Result { + let components = value + .split(|character: char| character.is_ascii_whitespace() || character == ',') + .filter(|component| !component.is_empty()) + .collect::>(); + if components.len() != 4 { + return Err(ImportError::new( + "provider icon viewBox must contain four finite decimal numbers", + )); } - if values.len() != 4 || values[2] <= 0 || values[3] <= 0 { + let decimal_places = components + .iter() + .map(|component| decimal_places(component)) + .collect::, _>>()?; + let max_decimal_places = decimal_places.iter().copied().max().unwrap_or(0); + debug_assert!(max_decimal_places <= 6); + let coordinate_scale = 10_i32.pow(max_decimal_places); + let mut integers = [0_i32; 4]; + for (index, component) in components.iter().enumerate() { + integers[index] = scaled_decimal(component, max_decimal_places)?; + } + if integers[2] <= 0 || integers[3] <= 0 { + return Err(ImportError::new( + "provider icon viewBox must have positive dimensions", + )); + } + Ok(ParsedViewBox { + integers, + coordinate_scale, + }) +} + +fn decimal_places(value: &str) -> Result { + let unsigned = value + .strip_prefix('-') + .or_else(|| value.strip_prefix('+')) + .unwrap_or(value); + let (integer, fraction) = unsigned.split_once('.').unwrap_or((unsigned, "")); + if integer.is_empty() + || !integer.bytes().all(|byte| byte.is_ascii_digit()) + || !fraction.bytes().all(|byte| byte.is_ascii_digit()) + || fraction.len() > 6 + { return Err(ImportError::new( - "provider icon viewBox must contain four integers with positive dimensions", + "provider icon viewBox must contain finite decimals with at most six places", )); } - Ok([values[0], values[1], values[2], values[3]]) + debug_assert!(fraction.len() <= 6); + Ok(fraction.len() as u32) +} + +fn scaled_decimal(value: &str, decimal_places: u32) -> Result { + let negative = value.starts_with('-'); + let unsigned = value + .strip_prefix('-') + .or_else(|| value.strip_prefix('+')) + .unwrap_or(value); + let (integer, fraction) = unsigned.split_once('.').unwrap_or((unsigned, "")); + let integer = integer + .parse::() + .map_err(|_| ImportError::new("provider icon viewBox is outside the supported range"))?; + let fraction_value = if fraction.is_empty() { + 0_i64 + } else { + fraction + .parse::() + .map_err(|_| ImportError::new("provider icon viewBox is invalid"))? + }; + debug_assert!(fraction.len() <= 6); + let fraction_places = fraction.len() as u32; + debug_assert!(decimal_places <= 6); + debug_assert!(fraction_places <= decimal_places); + let scale = 10_i64.pow(decimal_places); + let fraction_scale = 10_i64.pow(decimal_places - fraction_places); + let magnitude = integer + .checked_mul(scale) + .and_then(|value| value.checked_add(fraction_value * fraction_scale)) + .ok_or_else(|| ImportError::new("provider icon viewBox is outside the supported range"))?; + let signed = if negative { -magnitude } else { magnitude }; + i32::try_from(signed) + .map_err(|_| ImportError::new("provider icon viewBox is outside the supported range")) } fn collect_styles(document: &Document<'_>) -> Result, ImportError> { @@ -561,8 +695,11 @@ fn collect_styles(document: &Document<'_>) -> Result, I "provider stylesheet may define one fill property per class", )); } - validate_safe_value(value.trim())?; - fill = Some(value.trim().to_owned()); + let value = value.trim(); + if local_url_reference(value).is_none() { + validate_safe_value(value)?; + } + fill = Some(value.to_owned()); } let fill = match fill { Some(fill) => fill, @@ -584,25 +721,26 @@ fn collect_styles(document: &Document<'_>) -> Result, I fn identifier_map( document: &Document<'_>, + styles: &BTreeMap, provider_id: &str, icon_slug: &str, ) -> Result<(BTreeMap, bool), ImportError> { - let mut declared = BTreeSet::new(); + let mut declared = BTreeMap::new(); let mut referenced = BTreeSet::new(); for node in document.descendants() { if !node.is_element() { continue; } if let Some(identifier) = node.attribute("id") { - if !declared.insert(identifier.to_owned()) { - return Err(ImportError::new( - "provider icon declares a duplicate identifier", - )); - } + *declared.entry(identifier.to_owned()).or_insert(0_usize) += 1; } for attribute in node.attributes() { - if let Some(identifier) = local_reference(attribute.value()) { + if let Some(identifier) = local_url_reference(attribute.value()) { referenced.insert(identifier.to_owned()); + } else if attribute.name() == "href" { + if let Some(identifier) = fragment_reference(attribute.value()) { + referenced.insert(identifier.to_owned()); + } } else if attribute.value().to_ascii_lowercase().contains("url(") { return Err(ImportError::new( "provider icon contains a non-local URL reference", @@ -610,10 +748,15 @@ fn identifier_map( } } } + for value in styles.values() { + if let Some(identifier) = local_url_reference(value) { + referenced.insert(identifier.to_owned()); + } + } for identifier in &referenced { - if !declared.contains(identifier) { + if declared.get(identifier) != Some(&1) { return Err(ImportError::new( - "provider icon references an undeclared identifier", + "provider icon references an undeclared or duplicate identifier", )); } } @@ -625,7 +768,7 @@ fn identifier_map( ); } let mut has_unused_identifier = false; - for identifier in &declared { + for identifier in declared.keys() { if !referenced.contains(identifier) { has_unused_identifier = true; break; @@ -634,18 +777,24 @@ fn identifier_map( Ok((map, has_unused_identifier)) } -fn local_reference(value: &str) -> Option<&str> { +fn local_url_reference(value: &str) -> Option<&str> { let value = value.strip_prefix("url(#")?; let value = value.strip_suffix(')')?; if value.is_empty() { None } else { Some(value) } } +fn fragment_reference(value: &str) -> Option<&str> { + value.strip_prefix('#').filter(|value| !value.is_empty()) +} + struct SanitizeState<'a> { styles: &'a BTreeMap, identifiers: &'a BTreeMap, removed_metadata: bool, inlined_styles: bool, removed_unused_identifiers: bool, + view_box: [i32; 4], + coordinate_scale: i32, } fn serialize_element( @@ -674,7 +823,11 @@ fn serialize_element( if name == "defs" && parent_name != Some("svg") { return Err(ImportError::new("defs must be a direct child of SVG")); } - if matches!(name, "linearGradient" | "radialGradient") && parent_name != Some("defs") { + if matches!( + name, + "linearGradient" | "radialGradient" | "clipPath" | "mask" + ) && parent_name != Some("defs") + { return Err(ImportError::new( "gradients must be direct children of defs", )); @@ -684,25 +837,55 @@ fn serialize_element( "gradient stops must be direct children of gradients", )); } - if parent_name == Some("defs") && !matches!(name, "linearGradient" | "radialGradient") { - return Err(ImportError::new("defs may contain only gradients")); + if parent_name == Some("defs") + && !matches!( + name, + "linearGradient" | "radialGradient" | "clipPath" | "mask" + ) + { + return Err(ImportError::new( + "defs may contain only gradients, clip paths, or masks", + )); } let mut attributes = BTreeMap::new(); for attribute in node.attributes() { - if attribute.namespace().is_some() { + let is_xlink_href = attribute.name() == "href" + && attribute + .namespace() + .is_some_and(|namespace| namespace == XLINK_NAMESPACE); + if attribute.namespace().is_some() && !is_xlink_href { return Err(ImportError::new( "provider icon contains a namespaced attribute", )); } - let attribute_name = attribute.name(); + let attribute_name = if is_xlink_href { + "href" + } else { + attribute.name() + }; if attribute_name.starts_with("on") { return Err(ImportError::new( "provider icon contains an event handler attribute", )); } match attribute_name { - "version" => continue, + "version" | "data-name" | "xviewBox" => { + state.removed_metadata = true; + continue; + } + "viewBox" if is_root => { + attributes.insert( + "viewBox".to_owned(), + state + .view_box + .iter() + .map(i32::to_string) + .collect::>() + .join(" "), + ); + continue; + } "class" => { let fill = match state.styles.get(attribute.value()) { Some(fill) => fill, @@ -712,14 +895,35 @@ fn serialize_element( )); } }; - attributes.insert("fill".to_owned(), fill.clone()); + let fill = if let Some(identifier) = local_url_reference(fill) { + let mapped = state.identifiers.get(identifier).ok_or_else(|| { + ImportError::new("provider icon references an undeclared identifier") + })?; + format!("url(#{mapped})") + } else { + fill.clone() + }; + attributes.insert("fill".to_owned(), fill); + continue; + } + "style" => { + if attribute.value().trim() != "isolation: isolate" { + return Err(ImportError::new( + "provider icon contains an unsupported inline style", + )); + } + attributes.insert("isolation".to_owned(), "isolate".to_owned()); + state.inlined_styles = true; continue; } "id" => { if let Some(identifier) = state.identifiers.get(attribute.value()) { - if !matches!(name, "linearGradient" | "radialGradient") { + if !matches!( + name, + "linearGradient" | "radialGradient" | "clipPath" | "mask" + ) { return Err(ImportError::new( - "only gradients may retain provider icon identifiers", + "only local SVG resources may retain provider icon identifiers", )); } attributes.insert("id".to_owned(), identifier.clone()); @@ -735,7 +939,7 @@ fn serialize_element( "provider icon attribute '{attribute_name}' is not allowed" ))); } - let value = if let Some(identifier) = local_reference(attribute.value()) { + let value = if let Some(identifier) = local_url_reference(attribute.value()) { let mapped = match state.identifiers.get(identifier) { Some(mapped) => mapped, None => { @@ -744,12 +948,27 @@ fn serialize_element( )); } }; - if !matches!(attribute_name, "fill" | "stroke") { + if !matches!(attribute_name, "fill" | "stroke" | "clip-path" | "mask") { return Err(ImportError::new( - "local references are allowed only for fill or stroke", + "local URL references are not allowed for this attribute", )); } format!("url(#{mapped})") + } else if attribute_name == "href" { + let Some(identifier) = fragment_reference(attribute.value()) else { + return Err(ImportError::new( + "provider icon href must be a local fragment", + )); + }; + if !matches!(name, "linearGradient" | "radialGradient") { + return Err(ImportError::new( + "provider icon href is allowed only for gradients", + )); + } + let mapped = state.identifiers.get(identifier).ok_or_else(|| { + ImportError::new("provider icon references an undeclared identifier") + })?; + format!("#{mapped}") } else { validate_safe_value(attribute.value())?; attribute.value().to_owned() @@ -763,16 +982,39 @@ fn serialize_element( )); } } + if is_root && !attributes.contains_key("viewBox") { + attributes.insert( + "viewBox".to_owned(), + state + .view_box + .iter() + .map(i32::to_string) + .collect::>() + .join(" "), + ); + } + let mut definitions = String::new(); let mut children = String::new(); for child in node.children() { match child.node_type() { NodeType::Element => { if let Some(serialized) = serialize_element(child, false, Some(name), state)? { - children.push_str(&serialized); + if is_root && child.tag_name().name() == "defs" { + definitions.push_str(&serialized); + } else { + children.push_str(&serialized); + } + } + } + NodeType::Text if is_ignorable_text(child.text().unwrap_or_default()) => { + if child + .text() + .is_some_and(|text| text.contains('\u{200b}') || text.contains('\u{feff}')) + { + state.removed_metadata = true; } } - NodeType::Text if child.text().unwrap_or_default().trim().is_empty() => {} NodeType::Comment | NodeType::PI => state.removed_metadata = true, _ => { return Err(ImportError::new( @@ -784,6 +1026,14 @@ fn serialize_element( if name == "defs" && children.is_empty() { return Ok(None); } + if is_root && state.coordinate_scale != 1 && !children.is_empty() { + children = format!( + "{definitions}{children}", + state.coordinate_scale, + ); + } else if is_root && !definitions.is_empty() { + children = format!("{definitions}{children}"); + } let mut output = String::new(); output.push('<'); @@ -810,6 +1060,12 @@ fn serialize_element( Ok(Some(output)) } +fn is_ignorable_text(value: &str) -> bool { + value + .chars() + .all(|character| character.is_whitespace() || matches!(character, '\u{200b}' | '\u{feff}')) +} + fn validate_safe_value(value: &str) -> Result<(), ImportError> { let lowercase = value.to_ascii_lowercase(); if lowercase.contains("url(") @@ -888,26 +1144,50 @@ fn create_temporary_directory(parent: &Path) -> Result { fn render_notice(manifest: &ProviderPack) -> String { let mut notice = format!( - "# Stack provider icon pack notice\n\nProvider: {} (`{}`)\n\nSource: <{}>\n\nOfficial archive: <{}>\n\nRelease: {}\n\nArchive SHA-256: `{}`\n\nTerms: <{}>\n\nTerms reviewed: {} (review again after {})\n\n{}\n\n{}\n\n{}\n\nThis local pack was created from an archive selected by the user. Stack does not redistribute these asset bytes. Use and distribute generated diagrams only as permitted by the linked provider terms.\n\n## Icons\n", + "# Stack provider icon pack notice\n\nProvider: {} (`{}`)\n\n{}\n\n{}\n\n{}\n\nThis local pack was created from archives selected by the user. Stack does not redistribute these asset bytes. Use and distribute generated diagrams only as permitted by the linked provider and brand terms.\n\n## Sources\n", manifest.provider.name, manifest.provider.id, - manifest.source.page_url, - manifest.source.archive_url, - manifest.source.release, - manifest.source.archive_sha256, - manifest.source.terms_url, - manifest.source.terms_reviewed_at, - manifest.source.review_after, manifest.notice.attribution, manifest.notice.terms_summary, manifest.notice.non_endorsement, ); + render_notice_source(&mut notice, "primary", &manifest.source); + for source in &manifest.additional_sources { + render_notice_source(&mut notice, &source.id, &source.source); + } + notice.push_str("\n## Icons\n"); for icon in &manifest.icons { - notice.push_str(&format!("\n- `{}`: {}\n", icon.id, icon.product_name)); + let source_id = icon.asset.source_id.as_deref().unwrap_or("primary"); + let _ = write!( + notice, + "\n- `{}`: {} (source `{source_id}`)", + icon.id, icon.product_name + ); + if let Some(url) = &icon.brand_source_url { + let _ = write!(notice, "; brand source <{url}>"); + } + if let Some(url) = &icon.brand_guidelines_url { + let _ = write!(notice, "; brand guidelines <{url}>"); + } + notice.push('\n'); } notice } +fn render_notice_source(notice: &mut String, id: &str, source: &ProviderPackSource) { + let _ = write!( + notice, + "\n### `{id}`\n\n- Source: <{}>\n- Official archive: <{}>\n- Release: {}\n- Archive SHA-256: `{}`\n- Terms: <{}>\n- Terms reviewed: {} (review again after {})\n", + source.page_url, + source.archive_url, + source.release, + source.archive_sha256, + source.terms_url, + source.terms_reviewed_at, + source.review_after, + ); +} + fn sha256(bytes: &[u8]) -> String { let mut output = String::from("sha256:"); for byte in Sha256::digest(bytes) { @@ -925,243 +1205,12 @@ fn stable_io_error(kind: std::io::ErrorKind) -> &'static str { } } -fn provider_profile(provider: &str) -> Option> { - match provider { - "aws" => Some(AWS_PROFILE), - "gcp" => Some(GCP_PROFILE), - "azure" => Some(AZURE_PROFILE), - _ => None, - } -} - -const AWS_OUTPUTS: &[ProviderPackPermittedOutput] = &[ - ProviderPackPermittedOutput::ArchitectureDiagram, - ProviderPackPermittedOutput::Whitepaper, - ProviderPackPermittedOutput::Presentation, - ProviderPackPermittedOutput::DataSheet, - ProviderPackPermittedOutput::Poster, -]; - -const AWS_ICONS: &[IconProfile<'static>] = &[ - IconProfile { - slug: "s3", - subject: "Object storage service", - product_name: "Amazon Simple Storage Service (Amazon S3)", - node_kind: ProviderNodeKind::Storage, - archive_path: "Architecture-Service-Icons_07312026/Arch_Storage/48/Arch_Amazon-Simple-Storage-Service_48.svg", - }, - IconProfile { - slug: "sqs", - subject: "Managed message queue", - product_name: "Amazon Simple Queue Service (Amazon SQS)", - node_kind: ProviderNodeKind::Queue, - archive_path: "Architecture-Service-Icons_07312026/Arch_Application-Integration/48/Arch_Amazon-Simple-Queue-Service_48.svg", - }, - IconProfile { - slug: "lambda", - subject: "Serverless function service", - product_name: "AWS Lambda", - node_kind: ProviderNodeKind::Function, - archive_path: "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_AWS-Lambda_48.svg", - }, - IconProfile { - slug: "ec2", - subject: "Virtual compute service", - product_name: "Amazon Elastic Compute Cloud (Amazon EC2)", - node_kind: ProviderNodeKind::Service, - archive_path: "Architecture-Service-Icons_07312026/Arch_Compute/48/Arch_Amazon-EC2_48.svg", - }, - IconProfile { - slug: "rds", - subject: "Managed relational database service", - product_name: "Amazon Relational Database Service (Amazon RDS)", - node_kind: ProviderNodeKind::Database, - archive_path: "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-RDS_48.svg", - }, - IconProfile { - slug: "dynamodb", - subject: "Managed NoSQL database service", - product_name: "Amazon DynamoDB", - node_kind: ProviderNodeKind::Database, - archive_path: "Architecture-Service-Icons_07312026/Arch_Databases/48/Arch_Amazon-DynamoDB_48.svg", - }, - IconProfile { - slug: "eks", - subject: "Managed Kubernetes service", - product_name: "Amazon Elastic Kubernetes Service (Amazon EKS)", - node_kind: ProviderNodeKind::Service, - archive_path: "Architecture-Service-Icons_07312026/Arch_Containers/48/Arch_Amazon-Elastic-Kubernetes-Service_48.svg", - }, -]; - -const AWS_PROFILE: ProviderProfile<'static> = ProviderProfile { - id: "aws", - name: "Amazon Web Services", - page_url: "https://aws.amazon.com/architecture/icons/", - archive_url: "https://d1.awsstatic.com/onedam/marketing-channels/website/public/shared/architecture-icon-release/Icon-package_07312026.5846e92413caa21490223536cc97f1269e44fa92.zip", - archive_sha256: "sha256:d2d166c453526471749d520e0db022c459abef759d2946cf2dd1d1c992dc6526", - release: "Icon-package_07312026", - retrieved_at: "2026-09-04", - terms_url: "https://aws.amazon.com/trademark-guidelines/", - terms_reviewed_at: "2026-09-04", - review_after: "2026-12-03", - copyright: "Copyright Amazon Web Services, Inc. or its affiliates", - license_id: "LicenseRef-AWS-Architecture-Icons-Terms", - archive_license_included: false, - permitted_outputs: AWS_OUTPUTS, - product_name_nearby: true, - attribution: "AWS architecture icons are owned by Amazon Web Services, Inc. or its affiliates.", - terms_summary: "Use is limited to the architecture-diagram materials described by the official AWS Architecture Icons page and applicable AWS trademark guidelines.", - non_endorsement: "Amazon Web Services does not sponsor or endorse this diagram or Stack.", - icons: AWS_ICONS, -}; - -const GCP_OUTPUTS: &[ProviderPackPermittedOutput] = &[ - ProviderPackPermittedOutput::ArchitectureDiagram, - ProviderPackPermittedOutput::Documentation, -]; - -const GCP_ICONS: &[IconProfile<'static>] = &[ - IconProfile { - slug: "cloud-run", - subject: "Managed application runtime", - product_name: "Cloud Run", - node_kind: ProviderNodeKind::Service, - archive_path: "Unique Icons/Cloud Run/SVG/CloudRun-512-color-rgb.svg", - }, - IconProfile { - slug: "cloud-storage", - subject: "Object storage service", - product_name: "Cloud Storage", - node_kind: ProviderNodeKind::Storage, - archive_path: "Unique Icons/Cloud Storage/SVG/Cloud_Storage-512-color.svg", - }, - IconProfile { - slug: "compute-engine", - subject: "Virtual compute service", - product_name: "Compute Engine", - node_kind: ProviderNodeKind::Service, - archive_path: "Unique Icons/Compute Engine/SVG/ComputeEngine-512-color-rgb.svg", - }, - IconProfile { - slug: "gke", - subject: "Managed Kubernetes service", - product_name: "Google Kubernetes Engine", - node_kind: ProviderNodeKind::Service, - archive_path: "Unique Icons/GKE/SVG/GKE-512-color.svg", - }, - IconProfile { - slug: "bigquery", - subject: "Managed analytics data warehouse", - product_name: "BigQuery", - node_kind: ProviderNodeKind::Database, - archive_path: "Unique Icons/BigQuery/SVG/BigQuery-512-color.svg", - }, - IconProfile { - slug: "cloud-sql", - subject: "Managed relational database service", - product_name: "Cloud SQL", - node_kind: ProviderNodeKind::Database, - archive_path: "Unique Icons/Cloud SQL/SVG/CloudSQL-512-color.svg", - }, -]; - -const GCP_PROFILE: ProviderProfile<'static> = ProviderProfile { - id: "gcp", - name: "Google Cloud", - page_url: "https://cloud.google.com/icons", - archive_url: "https://services.google.com/fh/files/misc/core-products-icons.zip", - archive_sha256: "sha256:6531a10f58bc599c24d9a455d81dd757c1a03c3c43da9cddf639b859c1c1eece", - release: "Core product icons (May 2026 guide)", - retrieved_at: "2026-09-04", - terms_url: "https://about.google/brand-resource-center/", - terms_reviewed_at: "2026-09-04", - review_after: "2026-12-03", - copyright: "Copyright Google LLC", - license_id: "LicenseRef-Google-Cloud-Product-Icons-Terms", - archive_license_included: false, - permitted_outputs: GCP_OUTPUTS, - product_name_nearby: true, - attribution: "Google Cloud product icons are owned by Google LLC.", - terms_summary: "Use is limited to diagrams and technical documentation described by the official Google Cloud Icon Library and applicable Google brand terms.", - non_endorsement: "Google does not sponsor or endorse this diagram or Stack.", - icons: GCP_ICONS, -}; - -const AZURE_OUTPUTS: &[ProviderPackPermittedOutput] = &[ - ProviderPackPermittedOutput::ArchitectureDiagram, - ProviderPackPermittedOutput::TrainingMaterial, - ProviderPackPermittedOutput::Documentation, -]; - -const AZURE_ICONS: &[IconProfile<'static>] = &[ - IconProfile { - slug: "virtual-machines", - subject: "Virtual compute service", - product_name: "Azure Virtual Machines", - node_kind: ProviderNodeKind::Service, - archive_path: "Azure_Public_Service_Icons/Icons/compute/10021-icon-service-Virtual-Machine.svg", - }, - IconProfile { - slug: "storage-accounts", - subject: "Cloud storage account", - product_name: "Azure Storage Accounts", - node_kind: ProviderNodeKind::Storage, - archive_path: "Azure_Public_Service_Icons/Icons/storage/10086-icon-service-Storage-Accounts.svg", - }, - IconProfile { - slug: "azure-sql-database", - subject: "Managed relational database service", - product_name: "Azure SQL Database", - node_kind: ProviderNodeKind::Database, - archive_path: "Azure_Public_Service_Icons/Icons/databases/10130-icon-service-SQL-Database.svg", - }, - IconProfile { - slug: "aks", - subject: "Managed Kubernetes service", - product_name: "Azure Kubernetes Service (AKS)", - node_kind: ProviderNodeKind::Service, - archive_path: "Azure_Public_Service_Icons/Icons/containers/10023-icon-service-Kubernetes-Services.svg", - }, - IconProfile { - slug: "app-service", - subject: "Managed application platform", - product_name: "Azure App Service", - node_kind: ProviderNodeKind::Service, - archive_path: "Azure_Public_Service_Icons/Icons/app services/10035-icon-service-App-Services.svg", - }, -]; - -const AZURE_PROFILE: ProviderProfile<'static> = ProviderProfile { - id: "azure", - name: "Microsoft Azure", - page_url: "https://learn.microsoft.com/azure/architecture/icons/", - archive_url: "https://arch-center.azureedge.net/icons/Azure_Public_Service_Icons_V24.zip", - archive_sha256: "sha256:921594ccd1bf3d9c0a1bd7b6d924e050551a59342f2b353bb74bdcf761c35141", - release: "Azure_Public_Service_Icons_V24", - retrieved_at: "2026-09-04", - terms_url: "https://learn.microsoft.com/azure/architecture/icons/", - terms_reviewed_at: "2026-09-04", - review_after: "2026-12-03", - copyright: "Copyright Microsoft Corporation", - license_id: "LicenseRef-Microsoft-Azure-Architecture-Icons-Terms", - archive_license_included: true, - permitted_outputs: AZURE_OUTPUTS, - product_name_nearby: true, - attribution: "Azure architecture icons are owned by Microsoft Corporation.", - terms_summary: "Use is limited to architecture diagrams, training materials, and documentation under the terms included in the official Azure icon archive.", - non_endorsement: "Microsoft does not sponsor or endorse this diagram or Stack.", - icons: AZURE_ICONS, -}; - #[cfg(test)] mod tests { use super::*; + use crate::provider_catalog::CatalogIcon; use zip::write::SimpleFileOptions; - const TEST_OUTPUTS: &[ProviderPackPermittedOutput] = - &[ProviderPackPermittedOutput::ArchitectureDiagram]; - fn temporary_root(label: &str) -> PathBuf { std::env::temp_dir().join(format!("stack-cli-provider-{label}-{}", std::process::id())) } @@ -1209,52 +1258,67 @@ mod tests { read_icon_entry(&mut archive, entry_path) } - fn test_profile<'a>(archive_sha256: &'a str, archive_path: &'a str) -> ProviderProfile<'a> { - let icons = Box::leak(Box::new([IconProfile { - slug: "storage", - subject: "Object storage service", - product_name: "Example Storage", - node_kind: ProviderNodeKind::Storage, + fn test_profile(archive_sha256: &str, archive_path: &str) -> Result { + let mut profile = provider_catalog("aws")?; + profile.provider.id = "example".to_owned(); + profile.provider.name = "Example Cloud".to_owned(); + profile.source.page_url = "https://example.com/icons".to_owned(); + profile.source.archive_url = "https://example.com/icons.zip".to_owned(); + profile.source.archive_sha256 = archive_sha256.to_owned(); + profile.source.release = "fixture-1".to_owned(); + profile.source.terms_url = "https://example.com/terms".to_owned(); + profile.source.copyright = "Copyright Example Cloud".to_owned(); + profile.source.license_id = "LicenseRef-Example-Icons".to_owned(); + profile.additional_sources.clear(); + profile.notice.attribution = "Example Cloud owns the icons.".to_owned(); + profile.notice.terms_summary = "Architecture diagram use only.".to_owned(); + profile.notice.non_endorsement = "Example Cloud does not endorse Stack.".to_owned(); + profile.icons = vec![CatalogIcon { + id: "example:storage".to_owned(), + subject: "Object storage service".to_owned(), + product_name: "Example Storage".to_owned(), + brand_source_url: None, + brand_guidelines_url: None, + recommended_node_kind: ProviderNodeKind::Storage, + category: "Storage".to_owned(), + source_id: None, + archive_path: archive_path.to_owned(), + }]; + Ok(profile) + } + + fn import_test_profile( + profile: Result, + archive_path: &Path, + output_path: &Path, + ) -> Result { + import_profile( + profile.map_err(ImportError::new)?, archive_path, - }])); - ProviderProfile { - id: "example", - name: "Example Cloud", - page_url: "https://example.com/icons", - archive_url: "https://example.com/icons.zip", - archive_sha256, - release: "fixture-1", - retrieved_at: "2026-09-04", - terms_url: "https://example.com/terms", - terms_reviewed_at: "2026-09-04", - review_after: "2026-12-03", - copyright: "Copyright Example Cloud", - license_id: "LicenseRef-Example-Icons", - archive_license_included: false, - permitted_outputs: TEST_OUTPUTS, - product_name_nearby: true, - attribution: "Example Cloud owns the icons.", - terms_summary: "Architecture diagram use only.", - non_endorsement: "Example Cloud does not endorse Stack.", - icons, - } + &BTreeMap::new(), + output_path, + ) } #[test] fn audited_provider_profiles_have_expected_coverage() { assert_eq!( - provider_profile("aws").map(|profile| profile.icons.len()), - Some(7) + provider_catalog("aws").map(|profile| profile.icons.len()), + Ok(305) + ); + assert_eq!( + provider_catalog("gcp").map(|profile| profile.icons.len()), + Ok(45) ); assert_eq!( - provider_profile("gcp").map(|profile| profile.icons.len()), - Some(6) + provider_catalog("azure").map(|profile| profile.icons.len()), + Ok(639) ); assert_eq!( - provider_profile("azure").map(|profile| profile.icons.len()), - Some(5) + provider_catalog("simple-icons").map(|profile| profile.icons.len()), + Ok(62) ); - assert!(provider_profile("unknown").is_none()); + assert!(provider_catalog("unknown").is_err()); } #[test] @@ -1345,7 +1409,7 @@ mod tests { ), ( br#""#.as_slice(), - "four integers", + "finite decimals", ), ( br#""#.as_slice(), @@ -1353,11 +1417,20 @@ mod tests { ), ( br#""#.as_slice(), - "positive dimensions", + "four finite decimal numbers", ), ] { assert_svg_error(source, expected); } + + for value in [ + "999999999999999999999999", + "9223372036854775807", + "2147483648", + ] { + let decimal_places = u32::from(value == "9223372036854775807"); + assert!(scaled_decimal(value, decimal_places).is_err()); + } } #[test] @@ -1392,12 +1465,12 @@ mod tests { fn sanitizer_rejects_unsafe_structure_attributes_and_identifiers() { for (body, expected) in [ ( - "", + "", "duplicate identifier", ), ( "", - "undeclared identifier", + "undeclared or duplicate identifier", ), ( "", @@ -1418,7 +1491,7 @@ mod tests { ), ( "", - "only gradients may retain", + "only local SVG resources may retain", ), ( "", @@ -1426,7 +1499,7 @@ mod tests { ), ( "", - "only for fill or stroke", + "not allowed for this attribute", ), ("visible", "unsupported visible text"), ( @@ -1448,6 +1521,46 @@ mod tests { ); } + #[test] + fn sanitizer_preserves_local_resources_and_scales_decimal_view_boxes() { + let source = [ + r##""##, + "\u{200b}", + "", + ] + .concat(); + let processed = sanitize_svg(source.as_bytes(), "azure", "fixture"); + assert!(processed.is_ok()); + let Some(processed) = processed.ok() else { + return; + }; + assert_eq!(processed.view_box, [0, 0, 52_434, 44_650]); + assert!(processed.svg.contains("viewBox=\"0 0 52434 44650\"")); + assert!(processed.svg.contains("")); + assert!( + processed + .svg + .contains("href=\"#stack-azure-fixture-gradient-") + ); + assert!( + processed + .svg + .contains("clip-path=\"url(#stack-azure-fixture-gradient-") + ); + assert!( + processed + .svg + .contains("mask=\"url(#stack-azure-fixture-gradient-") + ); + assert!(processed.svg.contains("isolation=\"isolate\"")); + assert!(!processed.svg.contains("data-name")); + assert!( + processed + .transformations + .contains(&ProviderPackTransformation::ScaleViewBoxToIntegers) + ); + } + #[test] fn sanitizer_removes_empty_definitions_and_escapes_attributes() { let source = format!( @@ -1500,17 +1613,27 @@ mod tests { let output_path = root.join("pack"); assert!( - import_provider_pack("unknown", &root.join("missing.zip"), &output_path) - .err() - .is_some_and(|error| error.to_string().contains("unknown provider")) + import_provider_pack( + "unknown", + &root.join("missing.zip"), + &BTreeMap::new(), + &output_path, + ) + .err() + .is_some_and(|error| error.to_string().contains("unknown provider")) ); assert!( - import_provider_pack("aws", &root.join("missing.zip"), &output_path) - .err() - .is_some_and(|error| error.to_string().contains("file not found")) + import_provider_pack( + "aws", + &root.join("missing.zip"), + &BTreeMap::new(), + &output_path, + ) + .err() + .is_some_and(|error| error.to_string().contains("file not found")) ); assert!( - import_profile(test_profile("sha256:none", "icon.svg"), &root, &output_path) + import_test_profile(test_profile("sha256:none", "icon.svg"), &root, &output_path) .err() .is_some_and(|error| error.to_string().contains("not a file")) ); @@ -1522,7 +1645,7 @@ mod tests { assert!(large_archive.set_len(MAX_ARCHIVE_BYTES + 1).is_ok()); } assert!( - import_profile( + import_test_profile( test_profile("sha256:none", "icon.svg"), &large_archive_path, &output_path, @@ -1536,7 +1659,7 @@ mod tests { assert!(fs::write(&invalid_archive_path, invalid_archive).is_ok()); let invalid_digest = sha256(invalid_archive); assert!( - import_profile( + import_test_profile( test_profile(&invalid_digest, "icon.svg"), &invalid_archive_path, &output_path, @@ -1554,7 +1677,7 @@ mod tests { let parent_file = root.join("not-a-directory"); assert!(fs::write(&parent_file, b"file").is_ok()); assert!( - import_profile( + import_test_profile( test_profile(&sha256(&valid_archive), "icon.svg"), &valid_archive_path, &parent_file.join("pack"), @@ -1628,7 +1751,7 @@ mod tests { assert!(fs::write(&archive_path, &archive).is_ok()); assert!(fs::create_dir(&root).is_ok()); let digest = sha256(&archive); - let imported = import_profile( + let imported = import_test_profile( test_profile(&digest, "icons/storage.svg"), &archive_path, &output_path, @@ -1661,6 +1784,86 @@ mod tests { assert!(fs::remove_file(&archive_path).is_ok()); } + #[test] + fn local_import_requires_and_records_every_declared_source() { + let root = temporary_root("multiple-sources"); + let _ = fs::remove_dir_all(&root); + assert!(fs::create_dir(&root).is_ok()); + let primary_path = root.join("primary.zip"); + let categories_path = root.join("categories.zip"); + let primary = zip_with_entry( + "icons/storage.svg", + format!("").as_bytes(), + ); + let categories = zip_with_entry( + "icons/category.svg", + format!("").as_bytes(), + ); + assert!(fs::write(&primary_path, &primary).is_ok()); + assert!(fs::write(&categories_path, &categories).is_ok()); + + let Ok(mut profile) = test_profile(&sha256(&primary), "icons/storage.svg") else { + let _ = fs::remove_dir_all(&root); + return; + }; + let Ok(gcp) = provider_catalog("gcp") else { + let _ = fs::remove_dir_all(&root); + return; + }; + let Some(mut additional) = gcp.additional_sources.first().cloned() else { + let _ = fs::remove_dir_all(&root); + return; + }; + additional.source.archive_sha256 = sha256(&categories); + additional.source.archive_url = "https://example.com/categories.zip".to_owned(); + profile.additional_sources = vec![additional]; + profile.icons.push(CatalogIcon { + id: "example:category".to_owned(), + subject: "Example category".to_owned(), + product_name: "Example Category".to_owned(), + brand_source_url: None, + brand_guidelines_url: None, + recommended_node_kind: ProviderNodeKind::Service, + category: "Category".to_owned(), + source_id: Some("categories".to_owned()), + archive_path: "icons/category.svg".to_owned(), + }); + + assert!( + import_profile( + profile.clone(), + &primary_path, + &BTreeMap::new(), + &root.join("missing"), + ) + .err() + .is_some_and(|error| error.to_string().contains("missing local archive")) + ); + let unexpected = BTreeMap::from([("other".to_owned(), categories_path.clone())]); + assert!( + import_profile( + profile.clone(), + &primary_path, + &unexpected, + &root.join("unexpected"), + ) + .err() + .is_some_and(|error| error.to_string().contains("does not declare")) + ); + + let sources = BTreeMap::from([("categories".to_owned(), categories_path)]); + let imported = import_profile(profile, &primary_path, &sources, &root.join("pack")); + assert!(imported.is_ok()); + let manifest = fs::read_to_string(root.join("pack/manifest.json")).unwrap_or_default(); + assert!(manifest.contains("\"schemaVersion\": \"1.1\"")); + assert!(manifest.contains("\"sourceId\": \"categories\"")); + let notice = fs::read_to_string(root.join("pack/NOTICE.md")).unwrap_or_default(); + assert!(notice.contains("### `primary`")); + assert!(notice.contains("### `categories`")); + assert!(notice.contains("source `categories`")); + assert!(fs::remove_dir_all(&root).is_ok()); + } + #[test] fn local_import_rejects_hash_mismatch_existing_output_and_unsafe_paths() { let root = temporary_root("failures"); @@ -1670,7 +1873,7 @@ mod tests { assert!(fs::write(&archive_path, &archive).is_ok()); assert!(fs::create_dir(&root).is_ok()); - let mismatch = import_profile( + let mismatch = import_test_profile( test_profile( "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "../unsafe.svg", @@ -1685,7 +1888,7 @@ mod tests { ); let digest = sha256(&archive); - let unsafe_path = import_profile( + let unsafe_path = import_test_profile( test_profile(&digest, "../unsafe.svg"), &archive_path, &output_path, @@ -1697,7 +1900,7 @@ mod tests { ); assert!(fs::create_dir(&output_path).is_ok()); - let existing = import_profile( + let existing = import_test_profile( test_profile(&digest, "../unsafe.svg"), &archive_path, &output_path, diff --git a/src/provider_catalog.rs b/src/provider_catalog.rs new file mode 100644 index 0000000..572f07f --- /dev/null +++ b/src/provider_catalog.rs @@ -0,0 +1,148 @@ +//! Asset-free metadata for audited local provider imports. + +use serde::Deserialize; +use stack_theme::{ + ProviderNodeKind, ProviderPackAdditionalSource, ProviderPackIdentity, ProviderPackNotice, + ProviderPackRights, ProviderPackSource, +}; + +const AWS_CATALOG: &str = include_str!("../catalogs/aws.json"); +const GCP_CATALOG: &str = include_str!("../catalogs/gcp.json"); +const AZURE_CATALOG: &str = include_str!("../catalogs/azure.json"); +const SIMPLE_ICONS_CATALOG: &str = include_str!("../catalogs/simple-icons.json"); + +#[derive(Clone, Debug, Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub(crate) struct ProviderCatalog { + pub(crate) catalog_version: String, + pub(crate) pack_version: String, + pub(crate) provider: ProviderPackIdentity, + pub(crate) source: ProviderPackSource, + #[serde(default)] + pub(crate) additional_sources: Vec, + pub(crate) rights: ProviderPackRights, + pub(crate) notice: ProviderPackNotice, + pub(crate) icons: Vec, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub(crate) struct CatalogIcon { + pub(crate) id: String, + pub(crate) subject: String, + pub(crate) product_name: String, + #[serde(default)] + pub(crate) brand_source_url: Option, + #[serde(default)] + pub(crate) brand_guidelines_url: Option, + pub(crate) recommended_node_kind: ProviderNodeKind, + pub(crate) category: String, + #[serde(default)] + pub(crate) source_id: Option, + pub(crate) archive_path: String, +} + +pub(crate) fn provider_catalog(provider: &str) -> Result { + let source = match provider { + "aws" => AWS_CATALOG, + "gcp" => GCP_CATALOG, + "azure" => AZURE_CATALOG, + "simple-icons" => SIMPLE_ICONS_CATALOG, + _ => { + return Err(format!( + "unknown provider '{provider}'; expected aws, gcp, azure, or simple-icons" + )); + } + }; + let catalog: ProviderCatalog = serde_json::from_str(source) + .map_err(|_| format!("embedded provider catalog '{provider}' is invalid"))?; + if catalog.catalog_version != "1.0" { + return Err(format!( + "embedded provider catalog '{provider}' uses an unsupported version" + )); + } + Ok(catalog) +} + +pub(crate) fn provider_catalogs() -> Result, String> { + ["aws", "gcp", "azure", "simple-icons"] + .into_iter() + .map(provider_catalog) + .collect() +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeSet; + + use super::*; + + #[test] + fn embedded_catalogs_have_expected_complete_unique_coverage() { + let catalogs = provider_catalogs(); + assert!(catalogs.is_ok()); + let Ok(catalogs) = catalogs else { + return; + }; + assert_eq!( + catalogs + .iter() + .map(|catalog| (catalog.provider.id.as_str(), catalog.icons.len())) + .collect::>(), + [ + ("aws", 305), + ("gcp", 45), + ("azure", 639), + ("simple-icons", 62) + ] + ); + + let mut all_ids = BTreeSet::new(); + for catalog in &catalogs { + assert_eq!(catalog.catalog_version, "1.0"); + assert!(catalog.icons.iter().all(|icon| { + icon.id.starts_with(&format!("{}:", catalog.provider.id)) + && all_ids.insert(icon.id.as_str()) + })); + } + assert_eq!(all_ids.len(), 1_051); + } + + #[test] + fn previous_ids_and_requested_tool_ids_remain_available() { + let catalogs = provider_catalogs().unwrap_or_default(); + let ids = catalogs + .iter() + .flat_map(|catalog| catalog.icons.iter().map(|icon| icon.id.as_str())) + .collect::>(); + for expected in [ + "aws:s3", + "aws:sqs", + "aws:lambda", + "aws:ec2", + "aws:rds", + "aws:dynamodb", + "aws:eks", + "gcp:cloud-run", + "gcp:cloud-storage", + "gcp:compute-engine", + "gcp:gke", + "gcp:bigquery", + "gcp:cloud-sql", + "gcp:serverless", + "azure:virtual-machines", + "azure:storage-accounts", + "azure:azure-sql-database", + "azure:aks", + "azure:app-service", + "simple-icons:github", + "simple-icons:notion", + "simple-icons:linear", + "simple-icons:atlassian", + "simple-icons:jira", + "simple-icons:confluence", + ] { + assert!(ids.contains(expected), "missing {expected}"); + } + } +} diff --git a/tests/cli.rs b/tests/cli.rs index 3e1e153..c7ad4e7 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -150,11 +150,44 @@ fn help_and_version_are_stdout_only() -> Result<(), Box> { let version = stack(["--version"])?; assert_eq!(version.status.code(), Some(0)); - assert_eq!(version.stdout, b"stack 0.1.0\n"); + assert_eq!(version.stdout, b"stack 0.2.0\n"); assert!(version.stderr.is_empty()); Ok(()) } +#[test] +fn provider_catalog_commands_are_available_from_the_binary() -> Result<(), Box> { + let listed = stack(["icons", "list", "simple-icons", "linear"])?; + assert_eq!(listed.status.code(), Some(0)); + assert!(listed.stderr.is_empty()); + let listing = String::from_utf8(listed.stdout)?; + assert!(listing.contains("simple-icons:linear")); + assert!(listing.contains("Linear")); + assert!(!listing.contains(" Result<(), Box> { let directory = TestDirectory::new("format-in-place")?; From ade5eace77130cabb5d78454dbd17df92260e17d Mon Sep 17 00:00:00 2001 From: konojunya Date: Sat, 5 Sep 2026 00:45:45 +0900 Subject: [PATCH 2/2] Pin merged provider dependencies --- Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41491e5..145caeb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,7 +241,7 @@ source = "git+https://github.com/stack-sh/compiler.git?rev=4a18fac42afc2256a1bb3 [[package]] name = "stack-engine" version = "0.6.0" -source = "git+https://github.com/stack-sh/engine.git?rev=b4a85b09f0d75d5966d50dc76b39d7ea4989c823#b4a85b09f0d75d5966d50dc76b39d7ea4989c823" +source = "git+https://github.com/stack-sh/engine.git?rev=2c9adabd2ffee627ac5fe3ee26331b0ad75bceac#2c9adabd2ffee627ac5fe3ee26331b0ad75bceac" dependencies = [ "roxmltree", "serde_json", @@ -254,7 +254,7 @@ dependencies = [ [[package]] name = "stack-formatter" version = "0.1.0" -source = "git+https://github.com/stack-sh/engine.git?rev=b4a85b09f0d75d5966d50dc76b39d7ea4989c823#b4a85b09f0d75d5966d50dc76b39d7ea4989c823" +source = "git+https://github.com/stack-sh/engine.git?rev=2c9adabd2ffee627ac5fe3ee26331b0ad75bceac#2c9adabd2ffee627ac5fe3ee26331b0ad75bceac" dependencies = [ "stack-compiler", ] @@ -262,7 +262,7 @@ dependencies = [ [[package]] name = "stack-theme" version = "0.5.0" -source = "git+https://github.com/stack-sh/theme.git?rev=13e41b84167e810c36c3ab87fff2e1fda84a2b8f#13e41b84167e810c36c3ab87fff2e1fda84a2b8f" +source = "git+https://github.com/stack-sh/theme.git?rev=7e208d6a3c90d255799f390a4e8b86248c73caee#7e208d6a3c90d255799f390a4e8b86248c73caee" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index a29857d..177d128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,8 @@ roxmltree = "=0.21.1" serde = { version = "=1.0.229", features = ["derive"] } serde_json = "=1.0.151" sha2 = "=0.11.0" -stack-engine = { git = "https://github.com/stack-sh/engine.git", rev = "b4a85b09f0d75d5966d50dc76b39d7ea4989c823" } -stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "13e41b84167e810c36c3ab87fff2e1fda84a2b8f" } +stack-engine = { git = "https://github.com/stack-sh/engine.git", rev = "2c9adabd2ffee627ac5fe3ee26331b0ad75bceac" } +stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "7e208d6a3c90d255799f390a4e8b86248c73caee" } zip = { version = "=6.0.0", default-features = false, features = ["deflate-flate2-zlib-rs"] } [features]