From 69b42fc2caecba1deff07d8cb5cb237543a3b98c Mon Sep 17 00:00:00 2001 From: mayakost Date: Fri, 20 Mar 2026 19:59:49 -0400 Subject: [PATCH 1/2] add diagram skill --- .claude-plugin/marketplace.json | 11 +- .../deploy-on-aws/.claude-plugin/plugin.json | 9 +- plugins/deploy-on-aws/hooks/hooks.json | 16 + .../scripts/lib/aws4-shapes.json | 1242 +++++++++++++++++ .../deploy-on-aws/scripts/lib/drawio_url.py | 74 + .../scripts/lib/fix_icon_colors.py | 355 +++++ .../deploy-on-aws/scripts/lib/fix_nesting.py | 171 +++ .../scripts/lib/fix_step_badges.py | 496 +++++++ .../scripts/lib/post_process_drawio.py | 339 +++++ .../scripts/lib/validate_drawio.py | 226 +++ .../deploy-on-aws/scripts/validate-drawio.sh | 74 + .../skills/aws-architecture-diagram/SKILL.md | 514 +++++++ .../references/aws-diagram-guidelines.md | 528 +++++++ .../references/aws4-shapes.md | 231 +++ .../references/cli-export.md | 49 + .../references/diagram-templates-advanced.md | 50 + .../references/diagram-templates-basic.md | 111 ++ .../references/example-agentcore.drawio | 206 +++ .../example-complex-platform.drawio | 355 +++++ .../references/example-diagrams.md | 803 +++++++++++ .../references/example-event-driven.drawio | 349 +++++ .../references/example-microservices.drawio | 370 +++++ .../example-multi-region-active-active.drawio | 237 ++++ .../references/example-saas-backend.drawio | 454 ++++++ .../references/example-sketch.drawio | 235 ++++ .../references/group-styles.md | 78 ++ .../references/post-processing.md | 11 + .../references/style-guide.md | 99 ++ .../references/xml-structure.md | 193 +++ .../references/xml-templates-examples.md | 75 + .../references/xml-templates-structure.md | 102 ++ 31 files changed, 8056 insertions(+), 7 deletions(-) create mode 100644 plugins/deploy-on-aws/hooks/hooks.json create mode 100644 plugins/deploy-on-aws/scripts/lib/aws4-shapes.json create mode 100755 plugins/deploy-on-aws/scripts/lib/drawio_url.py create mode 100644 plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py create mode 100644 plugins/deploy-on-aws/scripts/lib/fix_nesting.py create mode 100644 plugins/deploy-on-aws/scripts/lib/fix_step_badges.py create mode 100644 plugins/deploy-on-aws/scripts/lib/post_process_drawio.py create mode 100755 plugins/deploy-on-aws/scripts/lib/validate_drawio.py create mode 100755 plugins/deploy-on-aws/scripts/validate-drawio.sh create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws4-shapes.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-advanced.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-agentcore.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-complex-platform.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-diagrams.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-event-driven.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-microservices.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-multi-region-active-active.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-saas-backend.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-sketch.drawio create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/post-processing.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-examples.md create mode 100644 plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-structure.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 32cdfbd7..5581047b 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,7 +11,7 @@ "plugins": [ { "category": "deployment", - "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment.", + "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment. Generate validated AWS architecture diagrams as draw.io XML.", "keywords": [ "aws", "aws agent skills", @@ -20,12 +20,15 @@ "cdk", "cloudformation", "infrastructure", - "pricing" + "pricing", + "diagrams", + "draw.io", + "architecture" ], "name": "deploy-on-aws", "source": "./plugins/deploy-on-aws", - "tags": ["aws", "deploy", "infrastructure", "cdk"], - "version": "1.1.0" + "tags": ["aws", "deploy", "infrastructure", "cdk", "diagrams"], + "version": "1.2.0" }, { "category": "location", diff --git a/plugins/deploy-on-aws/.claude-plugin/plugin.json b/plugins/deploy-on-aws/.claude-plugin/plugin.json index 9c74d834..b65ede56 100644 --- a/plugins/deploy-on-aws/.claude-plugin/plugin.json +++ b/plugins/deploy-on-aws/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "author": { "name": "Amazon Web Services" }, - "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment.", + "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment. Generate validated AWS architecture diagrams as draw.io XML.", "homepage": "https://github.com/awslabs/agent-plugins", "keywords": [ "aws", @@ -10,10 +10,13 @@ "infrastructure", "cdk", "cloudformation", - "pricing" + "pricing", + "diagrams", + "draw.io", + "architecture" ], "license": "Apache-2.0", "name": "deploy-on-aws", "repository": "https://github.com/awslabs/agent-plugins", - "version": "1.1.0" + "version": "1.2.0" } diff --git a/plugins/deploy-on-aws/hooks/hooks.json b/plugins/deploy-on-aws/hooks/hooks.json new file mode 100644 index 00000000..5e51d62c --- /dev/null +++ b/plugins/deploy-on-aws/hooks/hooks.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate-drawio.sh", + "timeout": 30 + } + ] + } + ] + } +} diff --git a/plugins/deploy-on-aws/scripts/lib/aws4-shapes.json b/plugins/deploy-on-aws/scripts/lib/aws4-shapes.json new file mode 100644 index 00000000..bba5f6af --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/aws4-shapes.json @@ -0,0 +1,1242 @@ +{ + "description": "Complete AWS4 shape registry for draw.io mxgraph.aws4.* namespace. Auto-generated from Sidebar-AWS4.js (service icons) + aws4.xml stencils (sub-resources).", + "source": "https://github.com/jgraph/drawio/blob/dev/src/main/webapp/js/diagramly/sidebar/Sidebar-AWS4.js", + "stencil_source": "https://github.com/jgraph/drawio/blob/dev/src/main/webapp/stencils/aws4.xml", + "version": "2026.03", + "generated_from": "draw.io v29.6.1 (2026-03-06)", + "categories": { + "customer_enablement": { + "fillColor": "#3F8624", + "shapes": [ + "activate", + "customer_enablement", + "iq", + "managed_services", + "professional_services", + "repost", + "repost_private", + "support", + "training_certification" + ] + }, + "business_applications": { + "fillColor": "#E7157B", + "shapes": [ + "alexa_for_business", + "appfabric", + "business_application", + "chime", + "chime_sdk", + "connect", + "end_user_messaging", + "honeycode", + "pinpoint", + "quick_suite", + "simple_email_service", + "supply_chain", + "wickr", + "workdocs", + "workmail" + ] + }, + "general": { + "fillColor": "#232F3D", + "shapes": [ + "all_products", + "general", + "marketplace", + "productIcon", + "resourceIcon" + ] + }, + "front_end_web_mobile": { + "fillColor": "#E7157B", + "shapes": [ + "amplify", + "device_farm", + "location_service", + "mobile" + ] + }, + "analytics": { + "fillColor": "#8C4FFF", + "shapes": [ + "analytics", + "athena", + "clean_rooms", + "cloudsearch2", + "data_exchange", + "data_pipeline", + "datazone", + "elasticsearch_service", + "emr", + "entity_resolution", + "finspace", + "glue", + "glue_databrew", + "glue_elastic_views", + "kinesis", + "kinesis_data_analytics", + "kinesis_data_firehose", + "kinesis_data_streams", + "kinesis_video_streams", + "lake_formation", + "managed_service_for_apache_flink", + "managed_streaming_for_kafka", + "quicksight", + "redshift", + "sagemaker_2", + "sql_workbench" + ] + }, + "ai_ml": { + "fillColor": "#01A88D", + "shapes": [ + "apache_mxnet_on_aws", + "app_studio", + "augmented_ai", + "bedrock", + "bedrock_agentcore", + "codeguru_2", + "codewhisperer", + "comprehend", + "comprehend_medical", + "deep_learning_amis", + "deep_learning_containers", + "deepcomposer", + "deeplens", + "deepracer", + "devops_guru", + "elastic_inference_2", + "forecast", + "fraud_detector", + "healthimaging", + "healthlake", + "healthscribe", + "kendra", + "lex", + "lookout_for_equipment", + "lookout_for_metrics", + "lookout_for_vision", + "machine_learning", + "monitron", + "neuron_ml_sdk", + "nova2", + "omics", + "panorama", + "personalize", + "polly", + "q", + "rekognition_2", + "sagemaker", + "sagemaker_ground_truth", + "sagemaker_studio_lab", + "tensorflow_on_aws", + "textract", + "torchserve", + "transcribe", + "translate" + ] + }, + "application_integration": { + "fillColor": "#E7157B", + "shapes": [ + "api_gateway", + "appflow", + "application_integration", + "appsync", + "b2b_data_interchange", + "eventbridge", + "express_workflow", + "managed_workflows_for_apache_airflow", + "mobile_application", + "mq", + "sns", + "sqs", + "step_functions" + ] + }, + "management_governance": { + "fillColor": "#E7157B", + "shapes": [ + "app_config", + "app_wizard", + "application_auto_scaling", + "autoscaling", + "backint_agent", + "chatbot", + "cloudformation", + "cloudtrail", + "cloudwatch_2", + "codeguru", + "config", + "control_tower", + "devops_agent", + "distro_for_opentelemetry", + "license_manager", + "managed_service_for_grafana", + "managed_service_for_prometheus", + "management_and_governance", + "management_console", + "opsworks", + "organizations", + "partner_central", + "personal_health_dashboard", + "proton", + "resilience_hub", + "resource_explorer", + "service_catalog", + "service_management_connector", + "systems_manager", + "systems_manager_incident_manager", + "telco_network_builder", + "trusted_advisor", + "user_notifications", + "well_architect_tool" + ] + }, + "networking": { + "fillColor": "#8C4FFF", + "shapes": [ + "app_mesh", + "application_recovery_controller", + "client_vpn", + "cloud_directory", + "cloud_map", + "cloud_wan", + "cloudfront", + "direct_connect", + "global_accelerator", + "networking_and_content_delivery", + "private_5g", + "route_53", + "rtb_fabric", + "site_to_site_vpn", + "transit_gateway", + "verified_access", + "vpc", + "vpc_lattice", + "vpc_privatelink" + ] + }, + "compute": { + "fillColor": "#ED7100", + "shapes": [ + "app_runner", + "auto_scaling2", + "auto_scaling3", + "batch", + "bottlerocket", + "compute", + "compute_optimizer", + "ec2", + "ec2_image_builder", + "elastic_beanstalk", + "elastic_fabric_adapter", + "elastic_load_balancing", + "elastic_vmware_service", + "fargate", + "genomics_cli", + "lambda", + "lightsail", + "lightsail_for_research", + "local_zones", + "nice_dcv", + "nice_enginframe", + "nitro_enclaves", + "outposts", + "outposts_1u_and_2u_servers", + "outposts_family", + "parallel_cluster", + "parallel_computing_service", + "serverless_application_repository", + "simspace_weaver", + "vmware_cloud_on_aws", + "wavelength" + ] + }, + "developer_tools": { + "fillColor": "#C925D1", + "shapes": [ + "application_composer", + "cloud9", + "cloud_control_api", + "cloud_development_kit", + "cloudshell", + "codeartifact", + "codebuild", + "codecatalyst", + "codecommit", + "codedeploy", + "codepipeline", + "codestar", + "command_line_interface", + "corretto", + "developer_tools", + "fault_injection_simulator", + "tools_and_sdks", + "xray" + ] + }, + "cloud_financial_management": { + "fillColor": "#3F8624", + "shapes": [ + "application_cost_profiler", + "budgets_2", + "cost_and_usage_report", + "cost_explorer", + "cost_management", + "custom_billing_manager", + "reserved_instance_reporting", + "savings_plans" + ] + }, + "migration_modernization": { + "fillColor": "#3F8624", + "shapes": [ + "application_discovery_service", + "cloudendure_migration", + "data_transfer_terminal", + "datasync", + "mainframe_modernization", + "migration_and_transfer", + "migration_evaluator", + "migration_hub", + "server_migration_service", + "snowball", + "snowball_edge", + "snowmobile", + "transfer_family", + "transfer_for_sftp", + "transform" + ] + }, + "end_user_computing": { + "fillColor": "#ED7100", + "shapes": [ + "appstream_20", + "desktop_and_app_streaming", + "worklink", + "workspaces", + "workspaces_family", + "workspaces_thin_client" + ] + }, + "ar_vr": { + "fillColor": "#E7157B", + "shapes": [ + "ar_vr", + "sumerian" + ] + }, + "security": { + "fillColor": "#DD344C", + "shapes": [ + "access_analyzer", "cognito", "guardduty", "inspector", "inspector_agent", + "macie", "secrets_manager", "security_hub", "waf", "waf_filtering_rule", + "shield", "shield_shield_advanced", + "identity_and_access_management", + "iam", "iam_access_analyzer", "iam_add_on", "iam_aws_sts", + "iam_aws_sts_alternate", "iam_data_encryption_key", + "iam_encrypted_data", "iam_long_term_security_credential", + "iam_mfa_token", "iam_permissions", "iam_role", "iam_temporary_security_credential", + "kms", "certificate_manager", "cloudhsm", + "detective", "firewall_manager", "artifact", + "audit_manager", "directory_service", "resource_access_manager", + "single_sign_on", "sso", + "artifact", + "audit_manager", + "certificate_manager_3", + "cloudhsm", + "cognito", + "detective", + "directory_service", + "firewall_manager", + "guardduty", + "identity_and_access_management", + "inspector", + "key_management_service", + "macie", + "network_firewall", + "payment_cryptography", + "private_certificate_authority", + "resource_access_manager", + "secrets_manager", + "security_agent", + "security_hub", + "security_identity_and_compliance", + "security_incident_response", + "security_lake", + "shield", + "signer", + "single_sign_on", + "verified_permissions", + "waf" + ] + }, + "database": { + "fillColor": "#C925D1", + "shapes": [ + "aurora", + "database", + "database_migration_service", + "documentdb_with_mongodb_compatibility", + "dynamodb", + "elasticache", + "keyspaces", + "managed_apache_cassandra_service", + "memorydb_for_redis", + "neptune", + "oracle_database_at_aws", + "rds", + "rds_on_vmware", + "timestream" + ] + }, + "storage": { + "fillColor": "#3F8624", + "shapes": [ + "backup", + "cloudendure_disaster_recovery", + "efs_infrequentaccess", + "efs_standard", + "elastic_block_store", + "elastic_file_system", + "file_cache", + "fsx", + "fsx_for_lustre", + "fsx_for_netapp_ontap", + "fsx_for_openzfs", + "fsx_for_windows_file_server", + "glacier", + "infrequent_access_storage_class", + "s3", + "s3_on_outposts_storage", + "snowcone", + "storage", + "storage_gateway" + ] + }, + "blockchain": { + "fillColor": "#ED7100", + "shapes": [ + "blockchain", + "managed_blockchain", + "quantum_ledger_database" + ] + }, + "quantum_technologies": { + "fillColor": "#ED7100", + "shapes": [ + "braket", + "quantum_technologies" + ] + }, + "contact_center": { + "fillColor": "#E7157B", + "shapes": [ + "contact_center" + ] + }, + "containers": { + "fillColor": "#ED7100", + "shapes": [ + "containers", + "ecr", + "ecs", + "ecs_anywhere", + "eks", + "eks_anywhere", + "eks_cloud", + "eks_distro", + "red_hat_openshift" + ] + }, + "customer_engagement": { + "fillColor": "#E7157B", + "shapes": [ + "customer_engagement" + ] + }, + "iot": { + "fillColor": "#1A9C37", + "shapes": [ + "iot", "iot_core", "iot_greengrass", "iot_analytics", "iot_events", + "iot_sitewise", "iot_device_defender", "iot_device_management", + "iot_things_graph", "iot_1click", "iot_button", "iot_certificate", + "iot_action", "iot_actuator", "iot_alexa_enabled_device", + "iot_alexa_skill", "iot_alexa_voice_service", "iot_bank", + "iot_bicycle", "iot_camera", "iot_car", "iot_cart", "iot_coffee_pot", + "iot_desired_state", "iot_device_gateway", "iot_dog", "iot_door_lock", + "iot_factory", "iot_fire_tv", "iot_fire_tv_stick", "iot_generic", + "iot_house", "iot_http", "iot_http2", "iot_lambda", "iot_lightbulb", + "iot_medical_emergency", "iot_mqtt", "iot_over_the_air_update", + "iot_police_emergency", "iot_policy", "iot_reported_state", + "iot_rule", "iot_sensor", "iot_servo", "iot_shadow", "iot_simulator", + "iot_thermostat", "iot_topic", "iot_travel", "iot_utility", + "iot_windfarm", "freertos", "iot_device_defender2", "iot_fleet_hub", + "iot_expresslink", "iot_fleetwise", "iot_roborunner", "iot_twinmaker" + ] + }, + "developer_tools": { + "fillColor": "#8C4FFF", + "shapes": [] + }, + "media_services": { + "fillColor": "#ED7100", + "shapes": [ + "deadline_cloud", + "elastic_transcoder", + "elemental", + "elemental_link", + "elemental_mediaconnect", + "elemental_mediaconvert", + "elemental_medialive", + "elemental_mediapackage", + "elemental_mediastore", + "elemental_mediatailor", + "interactive_video", + "media_services", + "nimble_studio", + "thinkbox_deadline", + "thinkbox_draft", + "thinkbox_frost", + "thinkbox_krakatoa", + "thinkbox_sequoia", + "thinkbox_stoke", + "thinkbox_xmesh" + ] + }, + "iot": { + "fillColor": "#3F8624", + "shapes": [ + "freertos", + "greengrass", + "internet_of_things", + "iot_1click", + "iot_analytics", + "iot_button", + "iot_core", + "iot_device_defender", + "iot_device_management", + "iot_edukit", + "iot_events", + "iot_expresslink", + "iot_fleetwise", + "iot_roborunner", + "iot_sitewise", + "iot_things_graph", + "iot_twinmaker" + ] + }, + "games": { + "fillColor": "#ED7100", + "shapes": [ + "gamekit", + "gamelift_2", + "gamelift_streams", + "games", + "gamesparks", + "lumberyard", + "open_3d_engine_2" + ] + }, + "satellite": { + "fillColor": "#8C4FFF", + "shapes": [ + "ground_station", + "satellite" + ] + }, + "robotics": { + "fillColor": "#ED7100", + "shapes": [ + "robomaker", + "robotics" + ] + }, + "serverless": { + "fillColor": "#ED7100", + "shapes": [ + "serverless" + ] + }, + "groups": { + "fillColor": "none", + "shapes": [ + "group", + "group_account", + "group_auto_scaling_group", + "group_aws_cloud", + "group_aws_cloud_alt", + "group_aws_step_functions_workflow", + "group_corporate_data_center", + "group_ec2_instance_contents", + "group_elastic_beanstalk", + "group_iot_greengrass", + "group_iot_greengrass_deployment", + "group_on_premise", + "group_region", + "group_security_group", + "group_spot_fleet", + "group_vpc2" + ] + }, + "sub_resources": { + "fillColor": "varies_by_parent_service", + "note": "Sub-resource icons from stencil XML. Use shape=mxgraph.aws4.{name} style (not resourceIcon).", + "shapes": [ + "a1_instance", + "access_analyzer", + "action", + "actuator", + "ad_connector", + "addon", + "agent", + "agent2", + "alarm", + "alert", + "alexa_enabled_device", + "alexa_skill", + "alexa_smart_home_skill", + "alexa_voice_service", + "ami", + "amplify_aws_amplify_studio", + "application", + "application_discovery_service_aws_agentless_collector", + "application_discovery_service_aws_discovery_agent", + "application_discovery_service_migration_evaluator_collector", + "application_load_balancer", + "apps", + "archive", + "athena_data_source_connectors", + "attribute", + "attributes", + "aurora_instance", + "aurora_instance_alt", + "authenticated_user", + "auto_scaling", + "automation", + "aws_backup_for_aws_cloudformation", + "aws_backup_legal_hold", + "aws_backup_support_for_amazon_fsx_for_netapp_ontap", + "aws_backup_vault_lock", + "aws_backup_virtual_machine_monitor", + "aws_cloud", + "aws_glue_data_quality", + "aws_glue_for_ray", + "aws_user_notifications", + "backup_audit_manager", + "backup_aws_backup_support_for_amazon_s3", + "backup_aws_backup_support_for_vmware_workloads", + "backup_backup_plan", + "backup_backup_restore", + "backup_compliance_reporting", + "backup_compute", + "backup_database", + "backup_gateway", + "backup_plan", + "backup_recovery_point_objective", + "backup_recovery_time_objective", + "backup_restore", + "backup_storage", + "backup_vault", + "backup_virtual_machine", + "backup_virtual_machine_monitor", + "bank", + "blockchain_resource", + "braket_chandelier", + "braket_chip", + "braket_embedded_simulator", + "braket_managed_simulator", + "braket_noise_simulator", + "braket_qpu", + "braket_simulator", + "braket_simulator_1", + "braket_simulator_2", + "braket_simulator_3", + "braket_simulator_4", + "braket_state_vector", + "braket_tensor_network", + "bucket", + "bucket_with_objects", + "budgets", + "bycicle", + "c4_instance", + "c5_instance", + "c5a", + "c5ad", + "c5d", + "c5n_instance", + "c6g_instance", + "c6gd", + "cache_node", + "cached_volume", + "camera", + "camera2", + "car", + "cart", + "certificate_manager", + "certificate_manager_2", + "change_set", + "chat", + "checklist", + "checklist_cost", + "checklist_fault_tolerant", + "checklist_performance", + "checklist_security", + "classic_load_balancer", + "client", + "cloud_digital_interface", + "cloud_extension_ros", + "cloud_map_resource", + "cloud_wan_segment_network", + "cloud_wan_transit_gateway_route_table_attachment", + "cloud_wan_virtual_pop", + "cloudfront_functions", + "cloudsearch", + "cloudtrail_cloudtrail_lake", + "cloudwatch", + "cloudwatch_cross_account_observability", + "cloudwatch_data_protection", + "cloudwatch_evidently", + "cloudwatch_logs", + "cloudwatch_metrics_insights", + "cloudwatch_rum", + "cloudwatch_synthetics", + "cluster", + "coffee_pot", + "cold_storage", + "connector", + "container_1", + "container_2", + "container_3", + "container_registry_image", + "corporate_data_center", + "corporate_data_center2", + "credentials", + "custom_event_bus_resource", + "customer_gateway", + "d2_instance", + "d3_instance", + "d3en_instance", + "data_encryption_key", + "data_exchange_for_apis", + "data_lake_resource_icon", + "data_set", + "data_stream", + "data_table", + "database_migration_workflow_job", + "datasync_discovery", + "datazone_business_data_catalog", + "datazone_data_portal", + "datazone_data_projects", + "db_instance", + "db_instance_read_replica", + "db_instance_standby", + "db_on_instance", + "db_on_instance2", + "default_event_bus_resource", + "dense_compute_node", + "dense_storage_node", + "deployment", + "deployments", + "desired_state", + "development_environment", + "devops_guru_insights", + "disk", + "document", + "documentdb_elastic_clusters", + "documents", + "documents2", + "documents3", + "door_lock", + "download_distribution", + "dynamodb_dax", + "dynamodb_standard_access_table_class", + "dynamodb_standard_infrequent_access_table_class", + "dynamodb_stream", + "ec2_aws_microservice_extractor_for_net", + "ec2_c6a_instance", + "ec2_c6gn_instance", + "ec2_c6i_instance", + "ec2_c6in_instance", + "ec2_c7g_instance", + "ec2_c7gn_instance", + "ec2_dl1_instance", + "ec2_g5_instance", + "ec2_g5g_instance", + "ec2_hpc6a_instance", + "ec2_hpc6id_instance", + "ec2_i4i_instance", + "ec2_im4gn_instance", + "ec2_inf2_instance", + "ec2_instance_contents", + "ec2_is4gen_instance", + "ec2_m1_mac_instance", + "ec2_m6a_instance", + "ec2_m6i_instance", + "ec2_m6idn_instance", + "ec2_m6in_instance", + "ec2_p4de_instance", + "ec2_r6a_instance", + "ec2_r6i_instance", + "ec2_r6idn_instance", + "ec2_r6in_instance", + "ec2_r7iz_instance", + "ec2_trn1_instance", + "ec2_vt1_instance", + "ec2_x2gd_instance", + "ec2_x2idn_instance", + "ec2_x2iedn_instance", + "ec2_x2iezn_instance", + "echo", + "ecs_copilot_cli", + "ecs_service", + "ecs_service_connect", + "ecs_task", + "edge_location", + "eks_on_outposts", + "elastic_block_store_amazon_data_lifecycle_manager", + "elastic_block_store_volume_gp3", + "elastic_file_system_elastic_throughput", + "elastic_file_system_infrequent_access", + "elastic_file_system_intelligent_tiering", + "elastic_file_system_one_zone", + "elastic_file_system_one_zone_infrequent_access", + "elastic_file_system_one_zone_standard", + "elastic_file_system_standard", + "elastic_file_system_standard_infrequent_access", + "elastic_inference", + "elastic_ip_address", + "elastic_network_adapter", + "elastic_network_interface", + "elasticache_for_memcached", + "elasticache_for_redis", + "elasticache_for_valkey", + "email", + "email_2", + "email_notification", + "emr_engine", + "emr_engine_mapr_m3", + "emr_engine_mapr_m5", + "emr_engine_mapr_m7", + "encrypted_data", + "endpoint", + "endpoints", + "event", + "event_event_based", + "event_resource", + "event_time_based", + "eventbridge_custom_event_bus_resource", + "eventbridge_default_event_bus_resource", + "eventbridge_pipes", + "eventbridge_saas_partner_event_bus_resource", + "eventbridge_scheduler", + "eventbridge_schema", + "eventbridge_schema_registry", + "external_sdk", + "external_toolkit", + "f1_instance", + "factory", + "file_cache_hybrid_nfs_linked_datasets", + "file_cache_on_premises_nfs_linked_datasets", + "file_cache_s3_linked_datasets", + "file_gateway", + "file_system", + "filtering_rule", + "finding", + "firetv", + "firetv_stick", + "fleet_management", + "flow_logs", + "folder", + "folders", + "forums", + "fsx_file_gateway", + "g3_instance", + "g4ad_instance", + "g4dn", + "game_tech", + "game_tech2", + "gamelift", + "gateway", + "gateway_load_balancer", + "gear", + "general_access_points", + "generic", + "generic_application", + "generic_database", + "generic_firewall", + "git_repository", + "glacier_deep_archive", + "global_secondary_index", + "globe", + "glue_crawlers", + "glue_data_catalog", + "group_availability_zone", + "group_elastic_load_balancing", + "group_subnet", + "group_vpc", + "h1_instance", + "habana_gaudi", + "hardware_board", + "hdfs_cluster", + "high_memory_instance", + "hosted_zone", + "house", + "http2_protocol", + "http_notification", + "http_protocol", + "i2", + "i3_instance", + "i3en", + "identity_access_management_iam_roles_anywhere", + "illustration_desktop", + "illustration_devices", + "illustration_notification", + "illustration_office_building", + "illustration_users", + "import_export", + "inf1", + "inferentia", + "instance", + "instance2", + "instance_with_cloudwatch", + "instance_with_cloudwatch2", + "instances", + "instances_2", + "intelligent_tiering", + "internet", + "internet_alt1", + "internet_alt2", + "internet_alt22", + "internet_gateway", + "inventory", + "iot_analytics_channel", + "iot_analytics_data_store", + "iot_analytics_dataset", + "iot_analytics_pipeline", + "iot_core_device_advisor", + "iot_core_device_location", + "iot_device_defender_iot_device_jobs", + "iot_device_gateway", + "iot_device_jobs_resource", + "iot_device_management_fleet", + "iot_device_tester", + "iot_greengrass_artifact", + "iot_greengrass_component", + "iot_greengrass_component_machine_learning", + "iot_greengrass_component_nucleus", + "iot_greengrass_component_private", + "iot_greengrass_component_public", + "iot_greengrass_interprocess_communication", + "iot_greengrass_protocol", + "iot_greengrass_recipe", + "iot_greengrass_stream_manager", + "iot_lorawan_protocol", + "iot_over_the_air_update", + "iot_sailboat", + "iot_sitewise_asset", + "iot_sitewise_asset_hierarchy", + "iot_sitewise_asset_model", + "iot_sitewise_asset_properties", + "iot_sitewise_data_streams", + "iot_thing_freertos_device", + "iot_thing_humidity_sensor", + "iot_thing_industrial_pc", + "iot_thing_plc", + "iot_thing_relay", + "iot_thing_stacklight", + "iot_thing_temperature_humidity_sensor", + "iot_thing_temperature_sensor", + "iot_thing_temperature_vibration_sensor", + "iot_thing_vibration_sensor", + "item", + "items", + "json_script", + "key_management_service_external_key_store", + "lambda_function", + "layers", + "license_manager_application_discovery", + "license_manager_license_blending", + "lightbulb", + "location_service_geofence", + "location_service_map", + "location_service_place", + "location_service_routes", + "location_service_track", + "logs", + "long_term_security_credential", + "m4_instance", + "m5_instance", + "m5a_instance", + "m5d_instance", + "m5dn_instance", + "m5n", + "m5n_instance", + "m5zn_instance", + "m6g_instance", + "m6gd_instance", + "mac_instance", + "magnifying_glass", + "magnifying_glass_2", + "mainframe_modernization_analyzer", + "mainframe_modernization_compiler", + "mainframe_modernization_converter", + "mainframe_modernization_developer", + "mainframe_modernization_runtime", + "maintenance_windows", + "managed_ms_ad", + "management_console2", + "mediaconnect_gateway", + "medical_emergency", + "mesh", + "message", + "metrics", + "mfa_token", + "migration_hub_refactor_spaces_applications", + "migration_hub_refactor_spaces_environments", + "migration_hub_refactor_spaces_services", + "mobile_client", + "mobile_hub", + "monitoring", + "mq_broker", + "mqtt_protocol", + "ms_sql_instance", + "ms_sql_instance_alternate", + "msk_amazon_msk_connect", + "multimedia", + "multiple_volumes_resource", + "mxgraph.aws4", + "mysql_db_instance", + "mysql_db_instance_alternate", + "namespace", + "nat_gateway", + "network_access_control_list", + "network_firewall_endpoints", + "network_load_balancer", + "non_cached_volume", + "notebook", + "nova", + "object", + "office_building", + "one_zone_ia", + "open_3d_engine", + "opensearch_dashboards", + "opensearch_ingestion", + "opensearch_observability", + "opensearch_service_cluster_administrator_node", + "opensearch_service_data_node", + "opensearch_service_index", + "opensearch_service_traces", + "opensearch_service_ultrawarm_node", + "opsworks_apps", + "opsworks_permissions", + "optimized_instance", + "oracle_db_instance", + "oracle_db_instance_alternate", + "organizations_account", + "organizations_account2", + "organizations_management_account", + "organizations_management_account2", + "organizations_organizational_unit", + "organizations_organizational_unit2", + "p2_instance", + "p3_instance", + "p3dn_instance", + "p4_instance", + "p4d_instance", + "parameter_store", + "patch_manager", + "peering", + "permissions", + "permissions_2", + "pinpoint_journey", + "police_emergency", + "policy", + "postgresql_instance", + "privatelink", + "programming_language", + "question", + "queue", + "quicksight_paginated_reports", + "r4_instance", + "r5_instance", + "r5a_instance", + "r5ad_instance", + "r5b_instance", + "r5d_instance", + "r5gd_instance", + "r5n", + "r5n_instance", + "r6g_instance", + "rdn_instance", + "rds_blue_green_deployments", + "rds_instance", + "rds_instance_alt", + "rds_mariadb_instance", + "rds_mariadb_instance_alt", + "rds_multi_az", + "rds_multi_az_db_cluster", + "rds_mysql_instance", + "rds_mysql_instance_alt", + "rds_optimized_writes", + "rds_oracle_instance", + "rds_oracle_instance_alt", + "rds_piop", + "rds_piops", + "rds_postgresql_instance", + "rds_postgresql_instance_alt", + "rds_proxy", + "rds_proxy_alt", + "rds_sql_server_instance", + "rds_sql_server_instance_alt", + "rds_trusted_language_extensions_for_postgresql", + "recover", + "redshift_auto_copy", + "redshift_data_sharing_governance", + "redshift_ml", + "redshift_query_editor_v20_light", + "redshift_ra3", + "redshift_streaming_ingestion", + "registry", + "rekognition", + "rekognition_image", + "rekognition_video", + "replication", + "replication_time_control", + "reported_state", + "rescue", + "resource", + "resources", + "role", + "route_53_application_recovery_controller", + "route_53_readiness_checks", + "route_53_resolver", + "route_53_resolver_dns_firewall", + "route_53_resolver_query_logging", + "route_53_routing_controls", + "route_table", + "router", + "rule", + "rule_2", + "rule_3", + "run_command", + "s3_batch_operations", + "s3_express_one_zone", + "s3_file_gateway", + "s3_multi_region_access_points", + "s3_object_lambda", + "s3_object_lambda_access_points", + "s3_object_lock", + "s3_on_outposts", + "s3_replication_time_control", + "s3_select", + "s3_storage_lens", + "s3_tables", + "s3_vectors", + "saas_event_bus_resource", + "sagemaker_canvas", + "sagemaker_geospatial_ml", + "sagemaker_model", + "sagemaker_notebook", + "sagemaker_shadow_testing", + "sagemaker_train", + "saml_token", + "search_documents", + "security_group", + "security_hub_finding", + "sensor", + "servers", + "service", + "servo", + "shadow", + "shield2", + "shield_shield_advanced", + "simple_ad", + "simple_storage_service_directory_bucket", + "simple_storage_service_s3_glacier_instant_retrieval", + "simulation", + "simulator", + "snapshot", + "source_code", + "spot_instance", + "sql_primary", + "sql_replica", + "ssl_padlock", + "stack", + "stack2", + "standard_ia", + "state_manager", + "streaming_distribution", + "sts", + "sts_alternate", + "systems_manager_application_manager", + "systems_manager_change_calendar", + "systems_manager_change_manager", + "systems_manager_compliance", + "systems_manager_distributor", + "systems_manager_opscenter", + "systems_manager_session_manager", + "t2_instance", + "t3_instance", + "t3a_instance", + "t4g_instance", + "table", + "tape_gateway", + "tape_storage", + "template", + "temporary_security_credential", + "textract_analyze_lending", + "thermostat", + "topic", + "topic_2", + "traditional_server", + "trainium_instance", + "transfer_family_aws_as2", + "transfer_for_ftp_resource", + "transfer_for_ftps_resource", + "transfer_for_sftp_resource", + "transit_gateway_attachment", + "travel", + "user", + "users", + "utility", + "vault", + "virtual_gateway", + "virtual_node", + "virtual_private_cloud", + "virtual_router", + "virtual_service", + "virtual_tape_library", + "volume", + "volume_gateway", + "vpc_access_points", + "vpc_carrier_gateway", + "vpc_network_access_analyzer", + "vpc_reachability_analyzer", + "vpc_traffic_mirroring", + "vpc_virtual_private_cloud_vpc", + "vpn_connection", + "vpn_gateway", + "waf_bad_bot", + "waf_bot", + "waf_bot_control", + "waf_labels", + "waf_managed_rule", + "waf_rule", + "well_architected_tool", + "windfarm", + "work_package", + "workspaces_family_amazon_workspaces", + "workspaces_family_amazon_workspaces_core", + "workspaces_workspaces_web", + "x1_instance", + "x1_instance2", + "x1e_instance", + "z1d_instance" + ] + } + } +} \ No newline at end of file diff --git a/plugins/deploy-on-aws/scripts/lib/drawio_url.py b/plugins/deploy-on-aws/scripts/lib/drawio_url.py new file mode 100755 index 00000000..c359dc04 --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/drawio_url.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +""" +drawio_url.py - Generate a draw.io URL from a .drawio file + +Compresses the XML and encodes it into a URL fragment that +opens directly in app.diagrams.net with the diagram loaded. + +Usage: python3 drawio_url.py [--open] + --open Also opens the URL in the default browser +""" + +import json +import subprocess +import sys +import zlib +from base64 import b64encode +from pathlib import Path +from platform import system +from urllib.parse import quote + + +def generate_url(file_path): + xml = Path(file_path).read_text(encoding="utf-8").strip() + + if not xml: + print("Error: File is empty", file=sys.stderr) + sys.exit(1) + + # 1. URL-encode the XML + encoded = quote(xml, safe="") + + # 2. Deflate compress (raw deflate, no zlib header) + # wbits=-15 gives raw deflate like Node's deflateRaw + compressed = zlib.compress(encoded.encode("utf-8"), level=9) + # Strip zlib header (first 2 bytes) and checksum (last 4 bytes) for raw deflate + raw_deflated = compressed[2:-4] + + # 3. Base64 encode + base64_str = b64encode(raw_deflated).decode("ascii") + + # 4. Build the JSON payload + payload = json.dumps({"type": "xml", "compressed": True, "data": base64_str}) + + # 5. URL-encode the payload and build the full URL + url = f"https://app.diagrams.net/#create={quote(payload, safe='')}" + + return url + + +def main(): + args = sys.argv[1:] + file_path = next((a for a in args if not a.startswith("--")), None) + should_open = "--open" in args + + if not file_path: + print("Usage: drawio_url.py [--open]", file=sys.stderr) + sys.exit(1) + + url = generate_url(file_path) + print(url) + + if should_open: + os_name = system() + if os_name == "Darwin": + cmd = "open" + elif os_name == "Windows": + cmd = "start" + else: + cmd = "xdg-open" + subprocess.run([cmd, url], check=False) + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py b/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py new file mode 100644 index 00000000..c66e9c92 --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python3 +"""Fix incorrect icon fillColor, container colors, and shape names. + +Fixes three types of issues: +1. Icon fillColor: resIcon cells with wrong category fill color +2. Container tint/stroke: parent container with wrong category colors +3. Shape renames: broken shape names (e.g., iam → identity_and_access_management) + +Uses only stdlib (xml.etree.ElementTree). No external deps. +""" + +import argparse +import xml.etree.ElementTree as ET + +# Broken shape names → correct shape names +SHAPE_RENAMES: dict[str, str] = { + "mxgraph.aws4.iam": "mxgraph.aws4.identity_and_access_management", + "mxgraph.aws4.iot_sensor": "mxgraph.aws4.sensor", +} + +# Map resIcon → (container_fillColor, container_strokeColor) +# Container = the 120x120 rounded rect that holds the icon +SHAPE_TO_CONTAINER: dict[str, tuple[str, str]] = { + # Networking → #EDE7F6 / #8C4FFF + "mxgraph.aws4.api_gateway": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.cloudfront": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.route_53": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.elastic_load_balancing": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.vpc": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.transit_gateway": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.direct_connect": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.cloud_map": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.nat_gateway": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.internet_gateway": ("#EDE7F6", "#8C4FFF"), + # Analytics → #EDE7F6 / #8C4FFF + "mxgraph.aws4.kinesis_data_streams": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.kinesis_data_firehose": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.athena": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.glue": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.quicksight": ("#EDE7F6", "#8C4FFF"), + # Developer Tools → #EDE7F6 / #8C4FFF + "mxgraph.aws4.codecommit": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.codepipeline": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.codebuild": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.codedeploy": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.xray": ("#EDE7F6", "#8C4FFF"), + "mxgraph.aws4.x_ray": ("#EDE7F6", "#8C4FFF"), + # Compute → #FFF2E8 / #ED7100 + "mxgraph.aws4.lambda": ("#FFF2E8", "#ED7100"), + "mxgraph.aws4.ec2": ("#FFF2E8", "#ED7100"), + "mxgraph.aws4.fargate": ("#FFF2E8", "#ED7100"), + "mxgraph.aws4.app_runner": ("#FFF2E8", "#ED7100"), + "mxgraph.aws4.ecs": ("#FFF2E8", "#ED7100"), + # Database → #F5E6F7 / #C925D1 + "mxgraph.aws4.dynamodb": ("#F5E6F7", "#C925D1"), + "mxgraph.aws4.rds": ("#F5E6F7", "#C925D1"), + "mxgraph.aws4.aurora": ("#F5E6F7", "#C925D1"), + "mxgraph.aws4.elasticache": ("#F5E6F7", "#C925D1"), + "mxgraph.aws4.dynamodb_streams": ("#F5E6F7", "#C925D1"), + "mxgraph.aws4.dynamodb_stream": ("#F5E6F7", "#C925D1"), + # Storage → #E8F5E9 / #3F8624 + "mxgraph.aws4.s3": ("#E8F5E9", "#3F8624"), + "mxgraph.aws4.ebs": ("#E8F5E9", "#3F8624"), + "mxgraph.aws4.efs": ("#E8F5E9", "#3F8624"), + # App Integration → #FCE4EC / #E7157B + "mxgraph.aws4.eventbridge": ("#FCE4EC", "#E7157B"), + "mxgraph.aws4.sqs": ("#FCE4EC", "#E7157B"), + "mxgraph.aws4.sns": ("#FCE4EC", "#E7157B"), + "mxgraph.aws4.step_functions": ("#FCE4EC", "#E7157B"), + # Security → #FFEBEE / #DD344C + "mxgraph.aws4.identity_and_access_management": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.cognito": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.waf": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.kms": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.secrets_manager": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.certificate_manager": ("#FFEBEE", "#DD344C"), + "mxgraph.aws4.directory_service": ("#FFEBEE", "#DD344C"), + # AI/ML → #E0F2F1 / #01A88D + "mxgraph.aws4.sagemaker": ("#E0F2F1", "#01A88D"), + "mxgraph.aws4.bedrock": ("#E0F2F1", "#01A88D"), + "mxgraph.aws4.bedrock_agentcore": ("#E0F2F1", "#01A88D"), + # IoT → #E8F5E9 / #1A9C37 + "mxgraph.aws4.iot_core": ("#E8F5E9", "#1A9C37"), + "mxgraph.aws4.iot_greengrass": ("#E8F5E9", "#1A9C37"), + "mxgraph.aws4.sensor": ("#E8F5E9", "#1A9C37"), + "mxgraph.aws4.iot_sensor": ("#E8F5E9", "#1A9C37"), + # Management → #FCE4EC / #E7157B + "mxgraph.aws4.cloudwatch": ("#FCE4EC", "#E7157B"), + "mxgraph.aws4.cloudtrail": ("#FCE4EC", "#E7157B"), + "mxgraph.aws4.systems_manager": ("#FCE4EC", "#E7157B"), +} + +# Map resIcon shape names to correct icon fillColor +SHAPE_TO_FILL: dict[str, str] = { + # Developer Tools → #8C4FFF (often confused with Database #C925D1) + "mxgraph.aws4.codecommit": "#8C4FFF", + "mxgraph.aws4.codepipeline": "#8C4FFF", + "mxgraph.aws4.codebuild": "#8C4FFF", + "mxgraph.aws4.codedeploy": "#8C4FFF", + "mxgraph.aws4.codestar": "#8C4FFF", + "mxgraph.aws4.codeartifact": "#8C4FFF", + "mxgraph.aws4.cloud9": "#8C4FFF", + "mxgraph.aws4.xray": "#8C4FFF", + "mxgraph.aws4.x_ray": "#8C4FFF", + # Networking/Analytics → #8C4FFF + "mxgraph.aws4.kinesis_data_streams": "#8C4FFF", + "mxgraph.aws4.kinesis_data_firehose": "#8C4FFF", + "mxgraph.aws4.athena": "#8C4FFF", + "mxgraph.aws4.glue": "#8C4FFF", + "mxgraph.aws4.quicksight": "#8C4FFF", + "mxgraph.aws4.api_gateway": "#8C4FFF", + "mxgraph.aws4.cloudfront": "#8C4FFF", + "mxgraph.aws4.route_53": "#8C4FFF", + "mxgraph.aws4.vpc": "#8C4FFF", + "mxgraph.aws4.elastic_load_balancing": "#8C4FFF", + "mxgraph.aws4.transit_gateway": "#8C4FFF", + "mxgraph.aws4.direct_connect": "#8C4FFF", + "mxgraph.aws4.cloud_map": "#8C4FFF", + # Compute → #ED7100 + "mxgraph.aws4.lambda": "#ED7100", + "mxgraph.aws4.ec2": "#ED7100", + "mxgraph.aws4.fargate": "#ED7100", + "mxgraph.aws4.app_runner": "#ED7100", + "mxgraph.aws4.ecs": "#ED7100", + # Database → #C925D1 + "mxgraph.aws4.dynamodb": "#C925D1", + "mxgraph.aws4.rds": "#C925D1", + "mxgraph.aws4.aurora": "#C925D1", + "mxgraph.aws4.elasticache": "#C925D1", + "mxgraph.aws4.dynamodb_streams": "#C925D1", + # Storage → #3F8624 + "mxgraph.aws4.s3": "#3F8624", + "mxgraph.aws4.ebs": "#3F8624", + "mxgraph.aws4.efs": "#3F8624", + # App Integration → #E7157B + "mxgraph.aws4.eventbridge": "#E7157B", + "mxgraph.aws4.sqs": "#E7157B", + "mxgraph.aws4.sns": "#E7157B", + "mxgraph.aws4.step_functions": "#E7157B", + # Security → #DD344C + "mxgraph.aws4.identity_and_access_management": "#DD344C", + "mxgraph.aws4.cognito": "#DD344C", + "mxgraph.aws4.waf": "#DD344C", + "mxgraph.aws4.kms": "#DD344C", + "mxgraph.aws4.secrets_manager": "#DD344C", + "mxgraph.aws4.certificate_manager": "#DD344C", + # AI/ML → #01A88D + "mxgraph.aws4.sagemaker": "#01A88D", + "mxgraph.aws4.bedrock": "#01A88D", + "mxgraph.aws4.bedrock_agentcore": "#01A88D", + # IoT → #1A9C37 + "mxgraph.aws4.iot_core": "#1A9C37", + "mxgraph.aws4.iot_greengrass": "#1A9C37", + "mxgraph.aws4.iot_analytics": "#1A9C37", + "mxgraph.aws4.sensor": "#1A9C37", + "mxgraph.aws4.iot_sensor": "#1A9C37", + # Management → #E7157B + "mxgraph.aws4.cloudwatch": "#E7157B", + "mxgraph.aws4.cloudtrail": "#E7157B", + "mxgraph.aws4.systems_manager": "#E7157B", +} + + +def _replace_style_value(style: str, key: str, new_val: str) -> str: + """Replace a key=value in a semicolon-delimited style string.""" + parts = [] + found = False + for part in style.split(";"): + if part.startswith(f"{key}="): + parts.append(f"{key}={new_val}") + found = True + else: + parts.append(part) + if not found: + parts.append(f"{key}={new_val}") + return ";".join(parts) + + +def _extract_color(value: str) -> str | None: + """Extract a hex color from a style value, unwrapping light-dark() if present. + + Examples: + '#E7157B' → '#E7157B' + 'light-dark(#DE227B,#DE227B)' → '#DE227B' + 'light-dark(#FCE4EC,#FCE4EC)' → '#FCE4EC' + """ + if not value: + return None + if "light-dark(" in value: + # Extract first color from light-dark(COLOR1,COLOR2) + inner = value.split("light-dark(", 1)[1].rstrip(")") + parts = inner.split(",") + return parts[0].strip() if parts else None + if value.startswith("#"): + return value + return None + + +def fix_icon_colors(tree: ET.ElementTree, verbose: bool = False) -> int: + """Fix icon fillColor, container tint/stroke, and broken shape names. + + 1. Rename broken resIcon shapes (e.g., iam → identity_and_access_management) + 2. Fix icon fillColor to match category + 3. Fix parent container fillColor/strokeColor to match category + + Returns total number of cells fixed. + """ + root_elem = tree.getroot() + fixed = 0 + + # Build a map of cell ID → cell element + cells: dict[str, ET.Element] = {} + for cell in root_elem.iter("mxCell"): + cid = cell.get("id") + if cid: + cells[cid] = cell + + for cell in root_elem.iter("mxCell"): + style = cell.get("style", "") + if "resIcon=" not in style: + continue + + # Extract resIcon value + res_icon = None + for part in style.split(";"): + if part.startswith("resIcon="): + res_icon = part.split("=", 1)[1] + break + + if res_icon is None: + continue + + # Step 1: Fix broken shape names + if res_icon in SHAPE_RENAMES: + new_icon = SHAPE_RENAMES[res_icon] + style = style.replace(f"resIcon={res_icon}", f"resIcon={new_icon}") + cell.set("style", style) + fixed += 1 + if verbose: + cid = cell.get("id", "?") + print(f" Renamed {cid}: {res_icon} -> {new_icon}") + res_icon = new_icon + + # Step 2: Fix icon fillColor + if res_icon in SHAPE_TO_FILL: + expected_fill = SHAPE_TO_FILL[res_icon] + current_fill = None + for part in style.split(";"): + if part.startswith("fillColor="): + current_fill = part.split("=", 1)[1] + break + + if current_fill is not None and current_fill.upper() != expected_fill.upper(): + style = _replace_style_value(style, "fillColor", expected_fill) + cell.set("style", style) + fixed += 1 + if verbose: + cid = cell.get("id", "?") + print(f" Fixed icon {cid}: fillColor {current_fill} -> {expected_fill}") + + # Step 3: Fix parent container tint/stroke/fontColor + if res_icon in SHAPE_TO_CONTAINER: + expected_tint, expected_stroke = SHAPE_TO_CONTAINER[res_icon] + parent_id = cell.get("parent", "") + parent_cell = cells.get(parent_id) + + if parent_cell is not None and parent_cell.get("vertex") == "1": + parent_style = parent_cell.get("style", "") + + # Only fix containers (rounded rect with strokeColor) + if "strokeColor=" not in parent_style: + continue + + # Check current container colors + cur_stroke_raw = None + cur_fill_raw = None + cur_font_raw = None + for part in parent_style.split(";"): + if part.startswith("strokeColor="): + cur_stroke_raw = part.split("=", 1)[1] + elif part.startswith("fillColor="): + cur_fill_raw = part.split("=", 1)[1] + elif part.startswith("fontColor="): + cur_font_raw = part.split("=", 1)[1] + + container_changed = False + + # Fix strokeColor — handle both plain and light-dark() wrapped + if cur_stroke_raw: + cur_stroke = _extract_color(cur_stroke_raw) + if cur_stroke and cur_stroke.upper() != expected_stroke.upper(): + if "light-dark" in cur_stroke_raw: + # Replace with light-dark using correct color + new_val = f"light-dark({expected_stroke},{expected_stroke})" + else: + new_val = expected_stroke + parent_style = _replace_style_value(parent_style, "strokeColor", new_val) + container_changed = True + + # Fix fillColor — handle both plain and light-dark() wrapped + if cur_fill_raw: + cur_fill = _extract_color(cur_fill_raw) + if cur_fill and cur_fill.upper() != expected_tint.upper(): + if "light-dark" in cur_fill_raw: + new_val = f"light-dark({expected_tint},{expected_tint})" + else: + new_val = expected_tint + parent_style = _replace_style_value(parent_style, "fillColor", new_val) + container_changed = True + + # Fix fontColor to match category stroke color + if cur_font_raw: + cur_font = _extract_color(cur_font_raw) + if cur_font and cur_font.upper() != expected_stroke.upper(): + # Don't touch light-dark font colors (those are for dark mode text) + if "light-dark" not in cur_font_raw: + parent_style = _replace_style_value(parent_style, "fontColor", expected_stroke) + container_changed = True + + if container_changed: + parent_cell.set("style", parent_style) + fixed += 1 + if verbose: + pid = parent_cell.get("id", "?") + print(f" Fixed container {pid}: fill={expected_tint} stroke={expected_stroke} font={expected_stroke}") + + return fixed + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Fix AWS service icon fill colors in draw.io files" + ) + parser.add_argument("file", help="Path to .drawio file") + parser.add_argument("--dry-run", action="store_true") + parser.add_argument("--verbose", "-v", action="store_true") + args = parser.parse_args() + + tree = ET.parse(args.file) + fixed = fix_icon_colors(tree, args.verbose) + + if fixed > 0: + print(f"Icons fixed: {fixed}") + if not args.dry_run: + ET.indent(tree, space=" ") + tree.write(args.file, encoding="unicode", xml_declaration=False) + print(f"Written: {args.file}") + else: + print("(dry run, no changes written)") + else: + print("No icon color issues found") + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/lib/fix_nesting.py b/plugins/deploy-on-aws/scripts/lib/fix_nesting.py new file mode 100644 index 00000000..f666b2bd --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/fix_nesting.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +"""Fix container nesting issues in draw.io AWS architecture diagrams. + +Region groups should use container=0 (decoration-only). If they use +container=1, services nested inside them cause edge routing failures +because draw.io's orthogonal auto-router can't resolve paths across +multiple container boundaries. + +This script: +1. Finds Region cells with container=1 in their style +2. Changes them to container=0 +3. Re-parents all children from the region to the region's parent +4. Converts children's relative coordinates to absolute by adding + the region's offset + +Uses only stdlib (xml.etree.ElementTree). No external deps. +""" + +import argparse +import xml.etree.ElementTree as ET + + +def get_style_dict(style_str: str) -> dict[str, str]: + result: dict[str, str] = {} + if not style_str: + return result + for part in style_str.split(";"): + part = part.strip() + if "=" in part: + k, v = part.split("=", 1) + result[k] = v + elif part: + result[part] = "" + return result + + +def set_style_value(style_str: str, key: str, value: str) -> str: + parts = [] + found = False + for part in style_str.split(";"): + part = part.strip() + if not part: + continue + if "=" in part: + k, v = part.split("=", 1) + if k == key: + parts.append(f"{key}={value}") + found = True + else: + parts.append(part) + else: + parts.append(part) + if not found: + parts.append(f"{key}={value}") + return ";".join(parts) + ";" + + +def get_geometry(cell: ET.Element) -> tuple[float, float, float, float] | None: + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + x = float(geom.get("x", "0")) + y = float(geom.get("y", "0")) + w = float(geom.get("width", "0")) + h = float(geom.get("height", "0")) + return (x, y, w, h) + return None + + +def offset_geometry(cell: ET.Element, dx: float, dy: float) -> None: + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + if geom.get("relative") == "1": + return # skip relative geometries (edge labels) + old_x = float(geom.get("x", "0")) + old_y = float(geom.get("y", "0")) + geom.set("x", str(round(old_x + dx, 1))) + geom.set("y", str(round(old_y + dy, 1))) + return + + +def is_region_container(cell: ET.Element) -> bool: + style = cell.get("style", "") + style_dict = get_style_dict(style) + return ( + "group_region" in style + and style_dict.get("container") == "1" + ) + + +def fix_nesting(tree: ET.ElementTree, verbose: bool = False) -> int: + root_elem = tree.getroot() + + cells: dict[str, ET.Element] = {} + for cell in root_elem.iter("mxCell"): + cid = cell.get("id") + if cid: + cells[cid] = cell + + fixed = 0 + + for cid, cell in list(cells.items()): + if not is_region_container(cell): + continue + + region_parent = cell.get("parent", "1") + region_geom = get_geometry(cell) + if region_geom is None: + continue + + rx, ry, rw, rh = region_geom + + if verbose: + print(f" Region {cid}: container=1 at ({rx},{ry}), parent={region_parent}") + + # Change region to container=0 + old_style = cell.get("style", "") + new_style = set_style_value(old_style, "container", "0") + cell.set("style", new_style) + + # Find all children of this region + children_moved = 0 + for child_id, child_cell in cells.items(): + if child_cell.get("parent") != cid: + continue + + # Re-parent to region's parent + child_cell.set("parent", region_parent) + + # Convert relative coordinates to absolute + if child_cell.get("edge") == "1": + # Edges don't need coordinate conversion + pass + else: + offset_geometry(child_cell, rx, ry) + + children_moved += 1 + + if verbose: + print(f" Changed to container=0, re-parented {children_moved} children (offset +{rx},+{ry})") + + fixed += 1 + + return fixed + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Fix Region container nesting in draw.io files" + ) + parser.add_argument("file", help="Path to .drawio file") + parser.add_argument("--dry-run", action="store_true") + parser.add_argument("--verbose", "-v", action="store_true") + args = parser.parse_args() + + tree = ET.parse(args.file) + fixed = fix_nesting(tree, args.verbose) + + if fixed > 0: + print(f"Regions fixed: {fixed}") + if not args.dry_run: + ET.indent(tree, space=" ") + tree.write(args.file, encoding="unicode", xml_declaration=False) + print(f"Written: {args.file}") + else: + print("(dry run, no changes written)") + else: + print("No region nesting issues found") + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py b/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py new file mode 100644 index 00000000..28306cbc --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py @@ -0,0 +1,496 @@ +#!/usr/bin/env python3 +"""Post-processing script to fix step badge overlap in draw.io XML files. + +Improved algorithm (v2): +1. Parse .drawio XML +2. Identify on-diagram step badges and all obstacles (icons, containers, + edge labels, text cells, other badges) +3. Resolve absolute coordinates by walking parent chains +4. Multi-pass iterative solver: + a. For each badge with overlap, try a grid of candidate positions + at multiple distances (30, 60, 90, 120, 150px) in 16 directions + b. Score each candidate by minimum clearance to ALL obstacles + (including already-placed badges) + c. Pick the candidate with the best (highest) minimum clearance + d. After moving all badges, re-check — repeat up to 3 passes +5. Update badge mxGeometry (convert back to parent-relative coords) + +Uses only stdlib (xml.etree.ElementTree). No external deps. +""" + +import argparse +import math +import re +import sys +import xml.etree.ElementTree as ET +from dataclasses import dataclass + + +@dataclass +class Rect: + x: float + y: float + w: float + h: float + + @property + def x2(self) -> float: + return self.x + self.w + + @property + def y2(self) -> float: + return self.y + self.h + + @property + def cx(self) -> float: + return self.x + self.w / 2 + + @property + def cy(self) -> float: + return self.y + self.h / 2 + + def overlaps(self, other: "Rect") -> bool: + return ( + self.x < other.x2 + and self.x2 > other.x + and self.y < other.y2 + and self.y2 > other.y + ) + + def min_clearance(self, other: "Rect") -> float: + """Minimum distance between edges. Negative if overlapping.""" + dx = max(other.x - self.x2, self.x - other.x2, 0) + dy = max(other.y - self.y2, self.y - other.y2, 0) + if dx == 0 and dy == 0: + ox = min(self.x2, other.x2) - max(self.x, other.x) + oy = min(self.y2, other.y2) - max(self.y, other.y) + return -min(ox, oy) + return (dx**2 + dy**2) ** 0.5 + + def expanded(self, margin: float) -> "Rect": + return Rect( + self.x - margin, + self.y - margin, + self.w + 2 * margin, + self.h + 2 * margin, + ) + + +def get_style_dict(style_str: str) -> dict[str, str]: + result: dict[str, str] = {} + if not style_str: + return result + for part in style_str.split(";"): + part = part.strip() + if "=" in part: + k, v = part.split("=", 1) + result[k] = v + elif part: + result[part] = "" + return result + + +def get_geometry(cell: ET.Element) -> Rect | None: + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + if geom.get("relative") == "1": + return None + x = float(geom.get("x", "0")) + y = float(geom.get("y", "0")) + w = float(geom.get("width", "0")) + h = float(geom.get("height", "0")) + return Rect(x, y, w, h) + return None + + +def resolve_edge_label_position( + cell: ET.Element, + cells: dict[str, ET.Element], + geom_cache: dict[str, Rect], +) -> Rect | None: + """Resolve an edge label's absolute position by finding the midpoint + of its parent edge's source and target, then applying offsets. + + Edge labels use relative geometry (position along the edge), which + can't be resolved by the normal parent-chain walk. Instead we: + 1. Find the parent edge's source and target cells + 2. Resolve source and target center points + 3. Interpolate along the edge based on the label's relative x + 4. Apply the perpendicular y offset + 5. Estimate label text width (~7px per char) for the bounding box + """ + parent_id = cell.get("parent", "1") + parent_cell = cells.get(parent_id) + if parent_cell is None or parent_cell.get("edge") != "1": + return None + + source_id = parent_cell.get("source") + target_id = parent_cell.get("target") + if not source_id or not target_id: + return None + + source_rect = resolve_absolute(source_id, cells, geom_cache) + target_rect = resolve_absolute(target_id, cells, geom_cache) + if source_rect is None or target_rect is None: + return None + + # Get label's relative position along edge + rel_x = 0.0 # default: midpoint + offset_y = 0.0 + for geom in cell: + if geom.tag == "mxGeometry": + rel_x = float(geom.get("x", "0")) + offset_y = float(geom.get("y", "0")) + break + + # Interpolate: rel_x of 0 = midpoint, -1 = source, +1 = target + t = 0.5 + rel_x * 0.5 # map [-1,1] -> [0,1] + cx = source_rect.cx + t * (target_rect.cx - source_rect.cx) + cy = source_rect.cy + t * (target_rect.cy - source_rect.cy) + offset_y + + # Estimate label dimensions from text content + value = cell.get("value", "") + text = re.sub(r"<[^>]+>", "", value).strip() + est_w = max(len(text) * 7, 40) # ~7px per char, min 40px + est_h = 16 # single line height + + label_rect = Rect(cx - est_w / 2, cy - est_h / 2, est_w, est_h) + return label_rect + + +def resolve_absolute( + cell_id: str, + cells: dict[str, ET.Element], + geom_cache: dict[str, Rect], +) -> Rect | None: + if cell_id in geom_cache: + return geom_cache[cell_id] + + cell = cells.get(cell_id) + if cell is None: + return None + + local = get_geometry(cell) + if local is None: + # Check if this is an edge label with relative geometry + style = cell.get("style", "") + if "edgeLabel" in style: + label_rect = resolve_edge_label_position(cell, cells, geom_cache) + if label_rect: + geom_cache[cell_id] = label_rect + return label_rect + return None + + parent_id = cell.get("parent", "1") + if parent_id in ("0", "1"): + geom_cache[cell_id] = local + return local + + parent_abs = resolve_absolute(parent_id, cells, geom_cache) + if parent_abs is None: + geom_cache[cell_id] = local + return local + + abs_rect = Rect( + parent_abs.x + local.x, + parent_abs.y + local.y, + local.w, + local.h, + ) + geom_cache[cell_id] = abs_rect + return abs_rect + + +def is_on_diagram_badge(cell: ET.Element) -> bool: + """On-diagram step badge: fillColor=#007CBD, numeric value, not in legend.""" + style = get_style_dict(cell.get("style", "")) + fill = style.get("fillColor", "").upper() + value = (cell.get("value") or "").strip() + cell_id = (cell.get("id") or "").lower() + parent_id = (cell.get("parent") or "").lower() + + if "legend" in cell_id or "legend" in parent_id: + return False + + if fill != "#007CBD": + return False + # Value may be plain "1" or HTML-wrapped like '1' + if re.match(r"^\d{1,2}$", value): + return True + stripped = re.sub(r"<[^>]+>", "", value).strip() + return bool(re.match(r"^\d{1,2}$", stripped)) + + +def classify_cell(cell: ET.Element) -> str: + """Classify a cell as 'badge', 'obstacle', or 'skip'.""" + cell_id = cell.get("id", "") + if cell_id in ("0", "1"): + return "skip" + + if is_on_diagram_badge(cell): + return "badge" + + style_str = cell.get("style", "") + style = get_style_dict(style_str) + + # Edges (not labels) — skip + if cell.get("edge") == "1": + return "skip" + + # Edge labels — skip (handled by model placement, not script). + # Badges and edge labels both annotate the same arrow, so they're + # inherently near each other. The model places them on opposite sides + # of the arrow. Script focuses on preventing badge-icon overlaps. + if "edgeLabel" in style_str: + return "skip" + + # Must be a vertex + if cell.get("vertex") != "1": + return "skip" + + geom = get_geometry(cell) + if geom is None or (geom.w == 0 and geom.h == 0): + return "skip" + + # Large architectural groups — skip (badges sit on these) + if "mxgraph.aws4.group" in style_str: + return "skip" + + # Legend panel backgrounds — skip + if "mxgraph.basic.rect" in style_str: + return "skip" + if "legend" in cell_id.lower(): + return "skip" + + # Invisible groups — skip + if style_str.startswith("group") or style.get("group") == "": + return "skip" + + # Line elements (title separator) — skip + if "line" in style_str.split(";") or style.get("line") == "": + return "skip" + + # Text cells — obstacle (badges shouldn't cover text) + if style_str.startswith("text;") or style.get("text") == "": + return "obstacle" + + # Everything else with geometry (icons, containers, etc.) — obstacle + return "obstacle" + + +def generate_candidates( + origin: Rect, + distances: list[float], + n_angles: int = 16, +) -> list[tuple[float, float]]: + """Generate candidate (dx, dy) offsets in a radial grid.""" + candidates: list[tuple[float, float]] = [] + for dist in distances: + for i in range(n_angles): + angle = 2 * math.pi * i / n_angles + dx = round(dist * math.cos(angle) / 10) * 10 # snap to 10px grid + dy = round(dist * math.sin(angle) / 10) * 10 + if (dx, dy) not in candidates: + candidates.append((dx, dy)) + return candidates + + +def compute_min_clearance( + badge_rect: Rect, + clearance: float, + obstacle_rects: list[Rect], +) -> float: + """Compute the minimum clearance between an expanded badge and all obstacles.""" + expanded = badge_rect.expanded(clearance) + min_c = float("inf") + for obs in obstacle_rects: + c = expanded.min_clearance(obs) + if c < min_c: + min_c = c + return min_c + + +def fix_badges( + tree: ET.ElementTree, + clearance: float = 10.0, + verbose: bool = False, +) -> int: + """Fix badge overlaps in-place. Returns number of badges moved.""" + root_elem = tree.getroot() + + cells: dict[str, ET.Element] = {} + for cell in root_elem.iter("mxCell"): + cid = cell.get("id") + if cid: + cells[cid] = cell + + # Classify all cells + badge_ids: list[str] = [] + obstacle_ids: list[str] = [] + + for cid, cell in cells.items(): + cls = classify_cell(cell) + if cls == "badge": + badge_ids.append(cid) + elif cls == "obstacle": + obstacle_ids.append(cid) + + if verbose: + print(f"Found {len(badge_ids)} badges, {len(obstacle_ids)} obstacles") + + # Semantic-aware placement: tight local search only. + # A badge at the right location with slight overlap is better than + # a badge at the wrong location with no overlap. + # Max 50px displacement keeps badges in their semantic zone (near their arrow). + distances = [10, 20, 30, 40, 50] + drift_penalty = 0.3 # penalize distance from original position + + total_moved = 0 + max_passes = 2 + + for pass_num in range(max_passes): + # Rebuild absolute positions from scratch each pass + geom_cache: dict[str, Rect] = {} + + # Resolve obstacle positions + obstacle_rects: list[Rect] = [] + for oid in obstacle_ids: + rect = resolve_absolute(oid, cells, geom_cache) + if rect: + obstacle_rects.append(rect) + + pass_moved = 0 + + for bid in badge_ids: + badge_abs = resolve_absolute(bid, cells, geom_cache) + if badge_abs is None: + continue + + # Build obstacle list = static obstacles + other badges (not self) + all_obstacles = list(obstacle_rects) + for other_bid in badge_ids: + if other_bid == bid: + continue + other_abs = resolve_absolute(other_bid, cells, geom_cache) + if other_abs: + all_obstacles.append(other_abs) + + # Check current clearance (with the tight clearance threshold) + current_clearance = compute_min_clearance( + badge_abs, clearance, all_obstacles + ) + + # Only move if actually overlapping (clearance < 0) + if current_clearance >= 0: + if verbose and pass_num == 0: + print( + f" Badge {bid} (value={cells[bid].get('value')}): " + f"OK (clearance={current_clearance:.0f})" + ) + continue + + # Generate local candidates (tight radius, stays near original) + candidates = generate_candidates(badge_abs, distances) + + best_dx, best_dy = 0.0, 0.0 + # Score = clearance - penalty * distance_from_origin + # This prefers closer positions even if clearance is slightly worse + current_score = current_clearance # distance=0 so no penalty + best_score = current_score + + for dx, dy in candidates: + candidate = Rect( + badge_abs.x + dx, + badge_abs.y + dy, + badge_abs.w, + badge_abs.h, + ) + c = compute_min_clearance(candidate, clearance, all_obstacles) + dist = (dx**2 + dy**2) ** 0.5 + score = c - drift_penalty * dist + + if score > best_score: + best_score = score + best_dx, best_dy = dx, dy + + if best_dx == 0 and best_dy == 0: + if verbose: + print( + f" Badge {bid} (value={cells[bid].get('value')}): " + f"no better position within 50px " + f"(clearance={current_clearance:.0f})" + ) + continue + + # Apply the move + cell = cells[bid] + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + old_x = float(geom.get("x", "0")) + old_y = float(geom.get("y", "0")) + geom.set("x", str(round(old_x + best_dx, 1))) + geom.set("y", str(round(old_y + best_dy, 1))) + break + + # Invalidate cache + if bid in geom_cache: + del geom_cache[bid] + + disp = (best_dx**2 + best_dy**2) ** 0.5 + new_clearance = best_score + drift_penalty * disp + pass_moved += 1 + if verbose: + print( + f" Badge {bid} (value={cells[bid].get('value')}): " + f"nudged ({best_dx:+.0f}, {best_dy:+.0f}), " + f"clearance {current_clearance:.0f} -> {new_clearance:.0f}, " + f"displacement {disp:.0f}px" + ) + + total_moved += pass_moved + if verbose and max_passes > 1: + print(f" Pass {pass_num + 1}: nudged {pass_moved} badges") + if pass_moved == 0: + break + + return total_moved + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Fix step badge overlap in draw.io XML files" + ) + parser.add_argument("file", help="Path to .drawio file") + parser.add_argument( + "--clearance", + type=float, + default=10.0, + help="Minimum clearance in px around badges (default: 10)", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Analyze but don't write changes", + ) + parser.add_argument( + "--verbose", "-v", + action="store_true", + help="Print detailed analysis", + ) + args = parser.parse_args() + + tree = ET.parse(args.file) + moved = fix_badges(tree, args.clearance, args.verbose) + + print(f"Badges moved: {moved}") + + if not args.dry_run and moved > 0: + ET.indent(tree, space=" ") + tree.write(args.file, encoding="unicode", xml_declaration=False) + print(f"Written: {args.file}") + elif args.dry_run and moved > 0: + print("(dry run, no changes written)") + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py b/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py new file mode 100644 index 00000000..4bf278ef --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py @@ -0,0 +1,339 @@ +#!/usr/bin/env python3 +"""Unified post-processing pipeline for draw.io AWS architecture diagrams. + +Chains all fixers in sequence: +1. fix_nesting — flatten Region container=1 to container=0 (fixes edge routing) +2. fix_step_badges — nudge overlapping step badges +3. fix_placement — move external actors below title block +4. fix_legend_size — resize legend panel to match diagram height + +Reads JSON from stdin (PostToolUse hook format) or accepts file path as argument. +Uses only stdlib. No external deps. +""" + +import argparse +import json +import sys +import xml.etree.ElementTree as ET +from pathlib import Path + +# Import sibling modules +SCRIPT_DIR = Path(__file__).parent +sys.path.insert(0, str(SCRIPT_DIR)) + +from fix_icon_colors import fix_icon_colors +from fix_nesting import fix_nesting +from fix_step_badges import fix_badges + + +def get_style_dict(style_str: str) -> dict[str, str]: + result: dict[str, str] = {} + if not style_str: + return result + for part in style_str.split(";"): + part = part.strip() + if "=" in part: + k, v = part.split("=", 1) + result[k] = v + elif part: + result[part] = "" + return result + + +def get_geometry(cell: ET.Element) -> dict[str, float] | None: + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + if geom.get("relative") == "1": + return None + return { + "x": float(geom.get("x", "0")), + "y": float(geom.get("y", "0")), + "w": float(geom.get("width", "0")), + "h": float(geom.get("height", "0")), + } + return None + + +def set_geometry(cell: ET.Element, **kwargs: float) -> None: + for geom in cell: + if geom.tag == "mxGeometry" and geom.get("as") == "geometry": + for k, v in kwargs.items(): + attr = {"x": "x", "y": "y", "w": "width", "h": "height"}[k] + geom.set(attr, str(round(v, 1))) + return + + +def fix_placement(tree: ET.ElementTree, verbose: bool = False) -> int: + """Move external actors outside the AWS Cloud boundary. + + External actors must be: + 1. Below the title block (y >= 140) + 2. Horizontally outside the AWS Cloud group rectangle + + If an external actor is horizontally inside AWS Cloud, move it to + x = aws_cloud_x - actor_width - 30 (30px gap left of cloud). + + Returns number of cells moved. + """ + root_elem = tree.getroot() + moved = 0 + title_bottom = 140 + + # Find the AWS Cloud group geometry + aws_cloud_geom = None + for cell in root_elem.iter("mxCell"): + style = cell.get("style", "") + if "group_aws_cloud" in style: + g = get_geometry(cell) + if g: + aws_cloud_geom = g + break + + min_y = title_bottom + if aws_cloud_geom is not None: + min_y = max(title_bottom, aws_cloud_geom["y"]) + + for cell in root_elem.iter("mxCell"): + cid = cell.get("id", "") + parent = cell.get("parent", "") + style = cell.get("style", "") + + # Only check cells at root level (parent="1") + if parent != "1": + continue + + # Skip non-vertices + if cell.get("vertex") != "1": + continue + + # Skip AWS groups, title elements, legend, badges, text + skip_patterns = [ + "mxgraph.aws4.group", + "group;", + "text;", + "line;", + "mxgraph.basic.rect", + "edgeLabel", + ] + if any(p in style for p in skip_patterns): + continue + + # Skip legend-related + if "legend" in cid.lower(): + continue + + # Skip step badges + if "step-" in cid.lower() and "fillColor=#007CBD" in style.upper(): + continue + + # Skip service containers (svc-group-*) — these are AWS services, not external actors + # After fix_nesting re-parents region children, services may end up at parent="1" + if cid.lower().startswith("svc-"): + continue + + # Skip cells with AWS service category stroke colors (service containers) + svc_stroke_colors = ["#ED7100", "#C925D1", "#8C4FFF", "#3F8624", "#E7157B", + "#DD344C", "#01A88D", "#1A9C37", "#DE227B"] + style_upper = style.upper() + if any(f"STROKECOLOR={c.upper()}" in style_upper.replace(" ", "") for c in svc_stroke_colors): + continue + + # Skip cells with resIcon for AWS services (not external actors) + if "resIcon=mxgraph.aws4." in style: + # Only external actor icons should be eligible + external_icons = ["users", "mobile_client", "iot_sensor", "iot_thing", + "internet", "traditional_server", "generic_database", "client"] + has_external_icon = any(f"resIcon=mxgraph.aws4.{icon}" in style for icon in external_icons) + if not has_external_icon: + continue + + # Check if this looks like an external actor container + is_external = False + value = (cell.get("value") or "").lower() + if any(kw in value for kw in ["user", "client", "mobile", "on-prem", "sensor", "iot device"]): + is_external = True + if any(kw in cid.lower() for kw in ["user", "client", "mobile", "sensor", "external", "onprem"]): + is_external = True + if "resIcon=mxgraph.aws4.users" in style or "resIcon=mxgraph.aws4.mobile_client" in style: + is_external = True + if "resIcon=mxgraph.aws4.iot_sensor" in style or "resIcon=mxgraph.aws4.iot_thing" in style: + is_external = True + if "fillColor=#f5f5f5" in style.lower() or "fillColor=light-dark(#F5F5F5" in style: + is_external = True + + if not is_external: + continue + + g = get_geometry(cell) + if g is None: + continue + + changed = False + + # Fix 1: Move below title block + if g["y"] < min_y: + old_y = g["y"] + set_geometry(cell, y=min_y) + g["y"] = min_y + changed = True + if verbose: + print(f" Moved {cid} down: y={old_y:.0f} -> y={min_y:.0f}") + + # Fix 2: Move horizontally outside AWS Cloud if overlapping + if aws_cloud_geom is not None: + cloud_x = aws_cloud_geom["x"] + cloud_x2 = cloud_x + aws_cloud_geom["w"] + actor_x = g["x"] + actor_x2 = actor_x + g["w"] + + # Check if actor overlaps AWS Cloud horizontally + if actor_x >= cloud_x and actor_x < cloud_x2: + # Actor starts inside cloud — move to left of cloud + new_x = cloud_x - g["w"] - 30 + if new_x < 20: + new_x = 20 # minimum left margin + set_geometry(cell, x=new_x) + changed = True + if verbose: + print(f" Moved {cid} left: x={actor_x:.0f} -> x={new_x:.0f} (outside AWS Cloud)") + + if changed: + moved += 1 + + return moved + + +def fix_legend_size(tree: ET.ElementTree, verbose: bool = False) -> int: + """Resize legend panel to match the diagram's main content height. + + Finds the legend-outer group and the AWS Cloud / Region group, + then sets legend height to span from the legend's y to the diagram bottom. + + Returns 1 if resized, 0 if no change needed. + """ + root_elem = tree.getroot() + + # Find legend-outer or legend-bg + legend_outer = None + legend_bg = None + for cell in root_elem.iter("mxCell"): + cid = cell.get("id", "") + if cid == "legend-outer": + legend_outer = cell + elif cid == "legend-bg": + legend_bg = cell + + if legend_outer is None: + return 0 + + legend_geom = get_geometry(legend_outer) + if legend_geom is None: + return 0 + + # Find the diagram's main content bottom (AWS Cloud or Region group) + diagram_bottom = 0 + for cell in root_elem.iter("mxCell"): + parent = cell.get("parent", "") + style = cell.get("style", "") + + # Look at root-level elements (parent="1") that are large groups + if parent == "1" and cell.get("vertex") == "1": + g = get_geometry(cell) + if g and g["h"] > 200: # large elements only + bottom = g["y"] + g["h"] + if bottom > diagram_bottom: + diagram_bottom = bottom + + if diagram_bottom <= 0: + return 0 + + # Target: legend spans from its y to diagram_bottom + some padding + target_height = diagram_bottom - legend_geom["y"] + 20 # 20px padding + current_height = legend_geom["h"] + + # Only resize if significantly different (>50px) + if abs(target_height - current_height) < 50: + return 0 + + if verbose: + print(f" Legend resize: {current_height:.0f} -> {target_height:.0f}") + + set_geometry(legend_outer, h=target_height) + + # Also resize legend-bg to match + if legend_bg is not None: + set_geometry(legend_bg, h=target_height) + + return 1 + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Unified post-processing for draw.io diagrams" + ) + parser.add_argument("file", nargs="?", help="Path to .drawio file (or reads JSON from stdin)") + parser.add_argument("--verbose", "-v", action="store_true") + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args() + + # Determine file path: from argument or stdin JSON (PostToolUse hook) + file_path = args.file + if file_path is None: + try: + data = json.load(sys.stdin) + file_path = data.get("tool_input", {}).get("file_path", "") + except (json.JSONDecodeError, KeyError): + pass + + if not file_path or not file_path.endswith((".drawio", ".drawio.xml")): + # Not a drawio file, exit silently (hook compatibility) + sys.exit(0) + + try: + tree = ET.parse(file_path) + except (ET.ParseError, FileNotFoundError) as e: + print(f"Error parsing {file_path}: {e}", file=sys.stderr) + sys.exit(1) + + changes = [] + + # 0. Fix Region container nesting (MUST run first — changes coordinates) + regions_fixed = fix_nesting(tree, verbose=args.verbose) + if regions_fixed > 0: + changes.append(f"nesting: {regions_fixed} regions flattened") + + # 1. Fix icon fill colors (before badge/layout fixes) + icons_fixed = fix_icon_colors(tree, verbose=args.verbose) + if icons_fixed > 0: + changes.append(f"icons: {icons_fixed} colors corrected") + + # 2. Fix step badge overlaps (15px clearance for visual breathing room) + badges_moved = fix_badges(tree, clearance=15.0, verbose=args.verbose) + if badges_moved > 0: + changes.append(f"badges: {badges_moved} moved") + + # 3. Fix external actor placement (below title + outside AWS Cloud) + actors_moved = fix_placement(tree, verbose=args.verbose) + if actors_moved > 0: + changes.append(f"placement: {actors_moved} actors repositioned") + + # 4. Fix legend panel sizing (match diagram height) + legend_resized = fix_legend_size(tree, verbose=args.verbose) + if legend_resized > 0: + changes.append("legend: resized to match diagram height") + + if changes: + summary = "; ".join(changes) + print(f"Post-processing: {summary}") + if not args.dry_run: + ET.indent(tree, space=" ") + tree.write(file_path, encoding="unicode", xml_declaration=False) + print(f"Written: {file_path}") + else: + print("(dry run, no changes written)") + else: + print("Post-processing: no changes needed") + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/lib/validate_drawio.py b/plugins/deploy-on-aws/scripts/lib/validate_drawio.py new file mode 100755 index 00000000..c05a704b --- /dev/null +++ b/plugins/deploy-on-aws/scripts/lib/validate_drawio.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 +""" +validate_drawio.py - Validates draw.io XML files for: +1. XML well-formedness +2. Correct draw.io structure (mxfile > diagram > mxGraphModel > root) +3. Valid AWS4 shape references +4. Edge integrity (source/target reference valid cell IDs) +5. Geometry validation (vertices have mxGeometry) +""" + +import json +import re +import sys +import xml.etree.ElementTree as ET +from pathlib import Path + +# Load valid AWS4 shapes +SCRIPT_DIR = Path(__file__).parent +shapes_data = json.loads((SCRIPT_DIR / "aws4-shapes.json").read_text()) + +valid_shapes = set() +for category in shapes_data["categories"].values(): + for shape in category["shapes"]: + valid_shapes.add(shape) + + +def validate(file_path): + errors = [] + warnings = [] + + # 1. Read file + try: + xml_text = Path(file_path).read_text(encoding="utf-8") + except Exception as e: + errors.append(f"Cannot read file: {e}") + return errors, warnings + + if not xml_text.strip(): + errors.append("File is empty") + return errors, warnings + + # Parse XML + try: + root = ET.fromstring(xml_text) + except ET.ParseError as e: + errors.append(f"XML parse error: {e}") + return errors, warnings + + # 2. Validate structure - accept both wrapped and bare + tag = root.tag + if tag == "mxfile": + diagrams = root.findall("diagram") + if not diagrams: + errors.append("Missing element inside .") + return errors, warnings + + models = root.findall(".//mxGraphModel") + if not models: + # Check for compressed content + for diag in diagrams: + content = (diag.text or "").strip() + if content and not content.startswith("<"): + name = diag.get("name", str(diagrams.index(diag))) + warnings.append( + f'Diagram "{name}" appears to be compressed. ' + "For full validation, use uncompressed XML format." + ) + if warnings: + return errors, warnings + errors.append("Missing element.") + return errors, warnings + + diagram_count = len(diagrams) + + elif tag == "mxGraphModel": + diagram_count = 1 + else: + errors.append( + "Missing root element. draw.io files must start with or ." + ) + return errors, warnings + + # 3. Validate cells + cells = root.iter("mxCell") if tag == "mxGraphModel" else root.findall(".//mxCell") + cells = list(cells) + + cell_ids = set() + has_root_cell = False + has_default_layer = False + aws_shapes_used = [] + invalid_shapes = [] + + for cell in cells: + cell_id = cell.get("id") + style = cell.get("style", "") + is_vertex = cell.get("vertex") == "1" + + if cell_id: + cell_ids.add(cell_id) + if cell_id == "0": + has_root_cell = True + if cell_id == "1" and cell.get("parent") == "0": + has_default_layer = True + + # Check AWS4 shapes + shape_match = re.search(r"shape=mxgraph\.aws4\.(\w+)", style) + if shape_match: + shape_name = shape_match.group(1) + aws_shapes_used.append(shape_name) + if shape_name not in valid_shapes: + invalid_shapes.append(shape_name) + + # Check resIcon references + res_icon_match = re.search(r"resIcon=mxgraph\.aws4\.(\w+)", style) + if res_icon_match: + res_icon_name = res_icon_match.group(1) + if res_icon_name not in valid_shapes: + invalid_shapes.append(f"resIcon:{res_icon_name}") + + # 5. Geometry validation for vertices + if is_vertex: + geometries = cell.findall("mxGeometry") + if not geometries: + warnings.append(f'Vertex cell id="{cell_id}" is missing .') + + if not has_root_cell: + errors.append('Missing root cell (mxCell id="0").') + if not has_default_layer: + errors.append('Missing default layer cell (mxCell id="1" parent="0").') + + # 4. Edge integrity + for cell in cells: + if cell.get("edge") == "1": + source = cell.get("source") + target = cell.get("target") + if source and source not in cell_ids: + errors.append( + f'Edge id="{cell.get("id")}" references non-existent source="{source}".' + ) + if target and target not in cell_ids: + errors.append( + f'Edge id="{cell.get("id")}" references non-existent target="{target}".' + ) + + # Report invalid AWS shapes + if invalid_shapes: + unique_invalid = list(dict.fromkeys(invalid_shapes)) + errors.append( + f"Invalid AWS4 shape references: {', '.join(unique_invalid)}. " + "Check the aws4-shapes.json registry for valid shape names." + ) + + # --- AWS Diagram Guideline Compliance Checks (warnings only) --- + + # 1. Background color check + graph_models = [root] if tag == "mxGraphModel" else root.findall(".//mxGraphModel") + for model in graph_models: + bg = model.get("background") + if bg != "#FFFFFF": + warnings.append( + 'No white background set on mxGraphModel. ' + 'AWS guidelines require background="#FFFFFF" (not transparent).' + ) + break + + # 2. Font color check + has_old_font_color = False + for cell in cells: + style = cell.get("style", "") + if cell.get("vertex") == "1" and "fontColor=#232F3E" in style: + has_old_font_color = True + break + if has_old_font_color: + warnings.append( + "Some shapes use fontColor=#232F3E. " + "AWS guidelines recommend #16191F or #000000 for label text." + ) + + # 4. Font size check + has_small_font = False + for cell in cells: + style = cell.get("style", "") + if cell.get("vertex") == "1": + fs_match = re.search(r"fontSize=(\d+)", style) + if fs_match and int(fs_match.group(1)) < 11: + has_small_font = True + break + if has_small_font: + warnings.append( + "Some shapes use fontSize below 11px. " + "AWS guidelines require 12px minimum (11px acceptable for dense layouts)." + ) + + # Summary info + if aws_shapes_used: + unique_count = len(set(aws_shapes_used)) + warnings.append( + f"AWS4 shapes used: {unique_count} unique shapes across {diagram_count} diagram(s)." + ) + + return errors, warnings + + +def main(): + if len(sys.argv) < 2: + print("Usage: validate_drawio.py ", file=sys.stderr) + sys.exit(1) + + file_path = sys.argv[1] + errors, warnings = validate(file_path) + + if errors: + print(f"VALIDATION FAILED for {file_path}:") + for e in errors: + print(f" ERROR: {e}") + if warnings: + for w in warnings: + print(f" INFO: {w}") + if not errors: + print(f"VALIDATION PASSED for {file_path}.") + + sys.exit(1 if errors else 0) + + +if __name__ == "__main__": + main() diff --git a/plugins/deploy-on-aws/scripts/validate-drawio.sh b/plugins/deploy-on-aws/scripts/validate-drawio.sh new file mode 100755 index 00000000..7db49627 --- /dev/null +++ b/plugins/deploy-on-aws/scripts/validate-drawio.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# validate-drawio.sh - PostToolUse hook for validating draw.io XML files +# Receives JSON on stdin with tool_input.file_path +# Outputs JSON with systemMessage field +# After validation passes, generates a draw.io URL for instant browser preview + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Read stdin (hook input JSON) +INPUT=$(cat) + +# Extract file path from the hook input +FILE_PATH=$(echo "$INPUT" | python3 -c " +import sys, json +try: + data = json.load(sys.stdin) + path = data.get('tool_input', {}).get('file_path', '') + print(path) +except: + print('') +" 2>/dev/null || echo "") + +# Only validate .drawio or .drawio.xml files +if [[ -z "$FILE_PATH" ]]; then + exit 0 +fi + +if [[ ! "$FILE_PATH" =~ \.(drawio|drawio\.xml)$ ]]; then + exit 0 +fi + +if [[ ! -f "$FILE_PATH" ]]; then + exit 0 +fi + +# Step 0: Run post-processing fixers BEFORE validation +# This fixes badge overlaps, external actor placement, and legend sizing +POST_RESULT=$(python3 "$SCRIPT_DIR/lib/post_process_drawio.py" "$FILE_PATH" 2>&1) || true + +# Step 1: Run the Python validator on the post-processed file +VALIDATE_RESULT=$(python3 "$SCRIPT_DIR/lib/validate_drawio.py" "$FILE_PATH" 2>&1) || true +VALIDATION_PASSED=false +if echo "$VALIDATE_RESULT" | grep -q "VALIDATION PASSED"; then + VALIDATION_PASSED=true +fi + +# Step 2: Only generate draw.io preview URL AFTER validation passes +URL_RESULT="" +if [[ "$VALIDATION_PASSED" == "true" ]]; then + URL_RESULT=$(python3 "$SCRIPT_DIR/lib/drawio_url.py" "$FILE_PATH" 2>/dev/null) || true +fi + +# Build the response message +FULL_RESULT="" +if [[ -n "$POST_RESULT" ]] && [[ "$POST_RESULT" != *"no changes needed"* ]]; then + FULL_RESULT="POST-PROCESSING: ${POST_RESULT} +" +fi +FULL_RESULT="${FULL_RESULT}${VALIDATE_RESULT}" +if [[ -n "$URL_RESULT" ]]; then + FULL_RESULT="${FULL_RESULT} +PREVIEW URL: ${URL_RESULT}" +fi + +if [[ -n "$FULL_RESULT" ]]; then + ESCAPED=$(echo "$FULL_RESULT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read().strip()))" 2>/dev/null || echo "\"$FULL_RESULT\"") + echo "{\"systemMessage\": $ESCAPED}" +else + echo '{"systemMessage": "draw.io XML validation passed. All AWS shapes are valid."}' +fi + +exit 0 diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md new file mode 100644 index 00000000..9bc5388c --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md @@ -0,0 +1,514 @@ +--- +name: aws-architecture-diagram +description: "Generate validated AWS architecture diagrams as draw.io XML using official AWS4 icon libraries. Use this skill whenever the user wants to create, generate, or design AWS architecture diagrams, cloud infrastructure diagrams, or system design visuals. Also triggers for requests to visualize existing infrastructure from CloudFormation, CDK, or Terraform code. Supports two modes: analyze an existing codebase to auto-generate diagrams, or brainstorm interactively from scratch. Exports .drawio files with optional PNG/SVG/PDF export via draw.io desktop CLI." +argument-hint: "[describe your architecture or say 'analyze' to scan codebase]" +allowed-tools: Bash, Write, Read, Glob, Grep +user-invocable: true +--- + +You are an AWS architecture diagram generator that produces draw.io XML files with official AWS4 icons. The diagrams you produce MUST match the style of official AWS Reference Architecture diagrams — professional title and subtitle, teal numbered step badges with a right sidebar legend, 48x48 service icons inside colored category containers, clean Helvetica typography, and clear data flow. + +**Reference examples**: Study `references/style-guide.md` for style rules, `references/xml-templates-structure.md` for XML code blocks, and `references/example-diagrams.md` for fully annotated XML examples with prompts. For AWS-official diagram standards, see `references/aws-diagram-guidelines.md`. Study these reference diagrams carefully — they demonstrate correct edge routing, waypoint usage, and layout: +- `references/example-multi-region-active-active.drawio` — Multi-region with Route 53, dual regions, DynamoDB Global Tables +- `references/example-event-driven.drawio` — Event-driven with branching, multiple edges per service, Auxiliary Services group +- `references/example-complex-platform.drawio` — 13+ service complex platform with waypoint routing around containers +- `references/example-microservices.drawio` — ECS Fargate microservices with multiple edges per service, external API, Auxiliary Services group placement +- `references/example-saas-backend.drawio` — Multi-tenant SaaS with 4 Lambdas, Step Functions orchestration dashed lines, fan-in to DynamoDB +- `references/example-sketch.drawio` — Sketch mode +- `references/example-agentcore.drawio` — AgentCore icons + +## Workflow + +### Step 1: Determine Mode + +**Mode A — Codebase Analysis:** If the user says "analyze", "scan", "from code", or references their existing project: +1. Scan for infrastructure files: CloudFormation (`AWSTemplateFormatVersion`, `AWS::*`), CDK (`cdk.json`, construct definitions), Terraform (`resource "aws_*"`) +2. Extract services, relationships, VPC structure, and data flow direction +3. Confirm discovered architecture with user before generating +4. Ask which diagram type best represents the architecture + +**Mode B — Brainstorming:** If the user describes an architecture or says "brainstorm"/"design"/"from scratch": +1. Ask 3-5 focused questions (purpose, services, scale, security, traffic pattern) +2. Propose the architecture with service recommendations and data flow +3. Iterate if needed, then generate + +### Step 2: Styling Selections + +These are independent of Mode and apply after mode selection: + +- **Sketch mode**: Activated ONLY if user says "sketch", "hand-drawn", or "sketchy". Default: OFF (Helvetica, no sketch attributes). See Sketch Mode in Style Rules below. +- **Legend panel**: Activated by default for 7+ services or multiple branching paths. Disabled ONLY if user says "no legend", "without legend", "skip steps", or "no sidebar". +- **Export format**: Check for format keywords (png, svg, pdf). Default: `.drawio` only. + +### Step 3: Generate Diagram XML + +1. Select the best diagram type (see Diagram Types) +2. Follow XML Generation Rules below +3. Apply style rules from `references/style-guide.md` +4. Apply styling selections from Step 2 + +### Step 4: Validate and Export + +1. Write the `.drawio` file to `./docs/` +2. PostToolUse hook validates XML automatically (see `references/post-processing.md` for the fixer pipeline) +3. If validation fails, fix errors and rewrite +4. Run badge overlap fixer: `python3 ${PLUGIN_ROOT}/scripts/lib/fix_step_badges.py ./docs/.drawio` +5. After validation passes, generate preview URL: + ```bash + python3 ${PLUGIN_ROOT}/scripts/lib/drawio_url.py ./docs/.drawio --open + ``` +6. If export format requested, run draw.io CLI (see `references/cli-export.md`) + +## Defaults + +- **Mode**: Brainstorm (if no codebase context) +- **Font**: `fontFamily=Helvetica` (Comic Sans MS only in sketch mode) +- **Icon size**: 48x48 inside 120x120 containers +- **Spacing**: 180px horizontal, 120px vertical between service group containers +- **Legend**: ALWAYS for 7+ services (unless user opts out) +- **Sketch mode**: OFF (unless user explicitly requests) +- **Dark mode**: `light-dark()` on all structural elements (always enabled) +- **Export format**: `.drawio` (unless user requests png/svg/pdf) +- **Grid**: OFF (`grid=0`) +- **File location**: `./docs/` directory +- **XML format**: Uncompressed, wrapped in `` + +## Error Handling + +- **XML validation failure**: Fix reported errors (malformed tags, missing IDs, invalid shapes), rewrite the file, re-validate +- **Shape not found**: Check `references/aws4-shapes.md` for valid `mxgraph.aws4.*` names +- **draw.io CLI not found**: Write `.drawio` file only, skip export, inform user to install draw.io desktop +- **Invalid edge source/target**: Verify all `source=` and `target=` IDs reference existing `mxCell` elements +- **Double hyphens in XML comments**: `--` is illegal inside `` per XML spec; use single hyphens or rephrase +- **Special characters**: Escape `&`, `<`, `>`, `"` in attribute values + +## Style Rules + +Full style details in `references/style-guide.md`. Critical rules that MUST be followed: + +- **Font**: ALL text MUST use `fontFamily=Helvetica;` (Comic Sans MS only in sketch mode) +- **Dark mode**: ALL structural elements MUST use `light-dark()` fills with `fillStyle=auto;`. See style-guide.md for the full color table. +- **Region groups**: MUST use `container=0` (decoration-only). Services use `parent="aws-cloud"` with absolute coords. +- **Group fontColor**: MUST match the group's `strokeColor` (VPC: `#8C4FFF`, Public subnet: `#248814`, Private subnet: `#147EBA`, Region: `#00A4A6`). NEVER use `fontColor=#AAB7B8`. +- **Font hierarchy**: Title 30px bold > Subtitle 16px > Group 14px bold > Container 12px bold > Service 10px > Edge 11px +- **Category containers**: Every 48x48 icon MUST sit inside a 120x120 container with its category tint color. See style-guide.md for the tint color table. +- **AgentCore**: Use `resIcon=mxgraph.aws4.bedrock_agentcore` (NOT `mxgraph.aws4.bedrock`) +- **Sketch mode**: Only when user requests it. Add `sketch=1;curveFitting=1;jiggle=2` to non-icon elements. Keep `sketch=0` on service icons. + +## Diagram Types + +- **VPC/Network**: VPC, subnets, security groups, NAT gateways, load balancers with group shapes +- **Serverless**: API Gateway, Lambda, DynamoDB, S3, Step Functions, EventBridge +- **Multi-Region**: Multiple regions with replication, Route 53, Global Accelerator +- **CI/CD Pipeline**: CodeCommit/GitHub -> CodeBuild -> CodeDeploy -> targets +- **Data Flow/Analytics**: Kinesis, S3, Glue, Athena, Redshift, QuickSight pipelines +- **Container**: ECS/EKS clusters, ECR, Fargate, load balancing +- **Hybrid**: On-premises + AWS with Direct Connect, VPN, Transit Gateway + +See `references/diagram-templates-basic.md` and `references/diagram-templates-advanced.md` for layout patterns. + +## XML Generation Rules + +### Required Structure + +Always use the full `mxfile` wrapper with `grid="0"`: + +```xml + + + + + + + + + + + +``` + +- Cell `id="0"` is the root layer (always required) +- Cell `id="1"` is the default parent layer (always required) +- All diagram elements use `parent="1"` unless nested inside a container +- Set `dx`/`dy` on mxGraphModel to control the visible canvas area (use larger values like `dx="1900" dy="2100"` for diagrams with negative-coordinate elements) + +### Cell ID Convention + +Use descriptive IDs for readability: `vpc-1`, `lambda-orders`, `s3-assets`, `edge-lambda-to-dynamo`. All IDs must be unique. + +### AWS4 Shape Styles + +ALWAYS use the `mxgraph.aws4.*` namespace. Reference `references/aws4-shapes.md` for the full list of valid shape names by category. + +There are two style patterns. Use the right one — the difference matters for rendering: + +**Service icon (resourceIcon)** — Use for ALL main AWS services (Lambda, S3, API Gateway, DynamoDB, etc.). This renders the colored square icon with the AWS service logo inside. The `points` array gives it 16 connection anchors for clean edge attachment: +``` +sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#16191F;fillColor={CATEGORY_COLOR};strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.{shape_name} +``` + +Example — an API Gateway icon at 78x78: +```xml + + + +``` + +**Sub-resource icon** — Use for service sub-components (glue_crawlers, glue_data_catalog, eventbridge_scheduler, ecs_task, etc.). These render as smaller flat icons without the square background. Use 48x48 size: +``` +sketch=0;outlineConnect=0;fontColor=#16191F;gradientColor=none;fillColor={CATEGORY_COLOR};strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.{shape_name} +``` + +Example — a Glue Crawler sub-resource at 48x48: +```xml + + + +``` + +### Adding Context to Labels + +Add descriptive sub-text to service labels using italic HTML — this helps readers understand each service's role without cluttering the diagram: +```xml +value="AWS Lambda<div><i>compress queries</i></div>" +``` +This renders as "AWS Lambda" with "compress queries" in italics below it. + +### Category Fill Colors + +| Category | fillColor | +|----------|-----------| +| Compute / Containers | `#ED7100` | +| Database | `#C925D1` | +| Analytics / Networking | `#8C4FFF` | +| Storage | `#3F8624` | +| Application Integration / Management | `#E7157B` | +| Security | `#DD344C` | +| AI/ML | `#01A88D` | +| General | `#232F3D` | + +### Font and Typography + +Per AWS diagram guidelines: +- **Font**: Amazon Ember (falls back to Helvetica/Arial in draw.io if not installed) +- **Font size**: 12px minimum (use `fontSize=11` only for dense layouts with 40px icons) +- **Font color**: `#16191F` for most labels. `#000000` is also acceptable. +- **Font weight**: Regular (`fontStyle=0`) for most text. Bold (`fontStyle=1`) for emphasis only. +- **Italics** preferred over underlines for secondary text — underlines create visual noise with arrows/lines. + +### Group Shapes (VPC, Subnets, Regions, AZs) + +Use group shapes to represent architectural boundaries. Reference `references/xml-structure.md` for all group style templates. + +**AWS Cloud group:** +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#16191F;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +**VPC group:** +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +**Public subnet:** +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +**Private subnet:** +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Edge Styles + +**Standard connection** (most common): +``` +edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1; +``` + +**Dashed (optional/async):** +``` +edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1; +``` + +The `orthogonalLoop=1;jettySize=auto` properties give edges better automatic routing around obstacles. Always include them on orthogonal edges. + +### Edge Labels + +Edge labels are separate child cells attached to an edge, NOT an attribute on the edge itself. Use `connectable="0"` and `edgeLabel` style with `relative="1"` geometry so the label positions itself along the edge: + +```xml + + + + + + + + +``` + +The `x` value on the geometry controls position along the edge (-1 = source end, 0 = midpoint, 1 = target end). The `y` value offsets perpendicular to the edge. + +### Cell IDs and Shape Styles + +- Use descriptive IDs: `vpc-1`, `lambda-orders`, `edge-lambda-to-dynamo` (all unique) +- **resourceIcon** pattern for main services (Lambda, S3, API Gateway, etc.) — 48x48 with 16 connection anchors. See `references/aws4-shapes.md` for valid shape names. +- **Sub-resource** pattern for service sub-components (glue_crawlers, ecs_task, etc.) — flat icons without square background +- Add italic sub-labels: `value="AWS Lambda<div><i>compress queries</i></div>"` + +### Label Placement (Mandatory) + +- **Container `value`** = functional category label (e.g., "DNS", "Compute", "Database", "Auth"). This is a short role descriptor, NOT the service name. +- **Icon `value`** = service name + optional italic sub-label with `verticalLabelPosition=bottom;verticalAlign=top` (e.g., `"Amazon DynamoDB<div><i>orders table</i></div>"`) +- NEVER put the service name on the container. NEVER put the category label on the icon. +- This pattern ensures each container visually reads as: **[Category Label]** at top → **[Icon]** → **[Service Name]** below icon. + +Full style strings for both patterns are in `references/style-guide.md`. Group style strings are in `references/group-styles.md`. + +### Edges + +Standard connection: `edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;` + +- Use `edgeStyle=orthogonalEdgeStyle` for right-angle connectors (most common) +- **Space nodes generously** -- at least 200px horizontal / 120px vertical gaps between icons +- **Always connect edges to service icons**, not to container/group shapes. If services are inside a container, target the icon cell ID (e.g., `target="lambda-1"`), not the container ID. Container shapes with `pointerEvents=0` won't render connections properly. +- Use `exitX`/`exitY` and `entryX`/`entryY` (values 0-1) to control which side of a node an edge connects to. Spread connections across different sides to prevent overlap +- **Leave room for arrowheads**: Ensure at least 20px of straight segment before the target and after the source. If the final segment is too short, the arrowhead overlaps the bend and looks broken +- When nodes are close together or nearly aligned, the auto-router may place a bend too close to a shape. Fix by increasing node spacing or adding explicit waypoints +- Add explicit **waypoints** when edges would overlap: + ```xml + + + + + + + + + ``` +- Use `rounded=1` on edges for cleaner bends +- Use `jettySize=auto` for better port spacing on orthogonal edges +- Align all nodes to a grid (multiples of 10) + +### Groups and Containers + +- Set `parent="containerId"` on children; children use **relative coordinates** +- Add `container=1;pointerEvents=0;` to group styles — **EXCEPT Region groups which MUST use `container=0`** +- **Region groups are decoration-only**: Use `container=0;pointerEvents=0;` on Region. Services positioned visually inside the region rectangle still have `parent="aws-cloud"` or `parent="1"` with absolute coordinates. This prevents nesting depth from breaking edge auto-routing. +- All group shapes MUST use `light-dark()` fills (see Style Rules above) +- Full group style strings: `references/group-styles.md` +- Container type reference: `references/xml-structure.md` +### When to use containers vs flat layout + +**Prefer flat layouts for most diagrams.** Place all service icons as direct children of the AWS Cloud group, and use text cells for section/column labels. This produces the cleanest edge routing because all icons share the same coordinate space. + +**Only use nested containers when they represent real infrastructure boundaries:** +- VPC, subnets, AZs, regions, security groups — these are real containment +- Step Functions workflows, ECS clusters — service-level grouping with a clear boundary + +**Do NOT use swimlane containers just to visually group columns** (e.g., "Authentication", "Data Layer", "API Layer"). This causes: +- Cross-container edge routing problems (edges between different containers produce messy orthogonal paths) +- Oversized containers with wasted space +- Coordinate confusion between parent frames + +Instead, use a text cell label above each column of icons: +```xml + + + +``` + +### External Actors + +Users/clients MUST be in a visible container (`fillColor=#f5f5f5`) with adaptive stroke. Icon `value=""`, label on the container. Edges connect to the container, not the icon. NEVER use `shape=actor`. See `references/xml-templates-structure.md`. +Set `parent="containerId"` on child cells. Children use **relative coordinates** within the container. + +### Container types + +| Type | Style | When to use | +|------|-------|-------------| +| **AWS Group** | `shape=mxgraph.aws4.group;grIcon=...;container=1;pointerEvents=0;` | VPC, subnets, regions, AZs | +| **Service workflow group** | `shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_step_functions_workflow;...` | Step Functions workflows, ECS clusters, or any service-level grouping | +| **Swimlane** (titled) | `swimlane;startSize=30;` | Only when the container itself needs connections (rare) | +| **Group** (invisible) | `group;` | No visual border needed, container has no connections | +| **Custom container** | Add `container=1;pointerEvents=0;` to any shape style | Any shape acting as a container without its own connections | + +**Step Functions workflow group** (useful for showing multi-step pipelines): +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_step_functions_workflow;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0 +``` + +**Placement rule**: External actors MUST be placed BELOW the title block. The title group occupies y=30 to y≈120. Place external actors at **y >= 140**. NEVER place any diagram element overlapping the title area. Vertically, align external actors with the top of the AWS Cloud group so the edge to the first service runs horizontally. + +**Clear path rule**: Do NOT place any service container between external actors and their first target (usually API Gateway). If Users is at the left and API Gateway is inside AWS Cloud, ensure no other service (like Cognito, WAF) is positioned in the direct horizontal path between them. Place auth/security services BELOW or ABOVE the main entry flow, not in line with it. + +## Layout Guidelines + +### Spacing and Overlap Prevention + +- 180px horizontal / 120px vertical gaps between 120px service group containers +- Group padding: 30px all sides, children start at y=40, x=20 minimum +- Account for ~20px label height below each 48x48 icon; 60px gap between vertical tiers +- Edge labels MUST NOT overlap service icons or description text — use `y` offset to shift +- 30px clearance between arrow endpoints and italic description text +- Place standalone services 200px+ from top-left corner of Region/VPC groups +- Align all positions to grid multiples of 10 + +### Complex Diagram Scaling (13+ services) + +For diagrams with 13+ services, increase spacing to prevent crowding: +- Horizontal spacing: 220px (up from 180px) +- Vertical spacing: 160px (up from 120px) +- Page size: `pageWidth=1600;pageHeight=1200` minimum +- Route long-distance edges around service clusters using explicit waypoints (``) +- Arrows MUST NOT cross through service container rectangles — use waypoints to route around them +- For edges connecting services that are NOT horizontally or vertically adjacent, ALWAYS add explicit waypoints to route around intervening containers + +### Edge Routing + +Study `references/example-event-driven.drawio` and `references/example-complex-platform.drawio` for correct edge routing patterns. + +**Basic rules:** +- Use `edgeStyle=orthogonalEdgeStyle` for right-angle connectors +- For simple adjacent connections (A directly next to B), let draw.io auto-route — do NOT set entry/exit points +- Leave 20px straight segment before target and after source for arrowheads +- Edges always leave PERPENDICULAR to the container face and route OUTWARD — the first segment after exiting a container MUST move AWAY from the container, never back into it. If an edge exits from the bottom (`exitY=1`), the first segment goes DOWN. If it exits right (`exitX=1`), the first segment goes RIGHT. + +**Multiple edges from one service** (CRITICAL): +- When a service has 2+ outgoing edges, each edge MUST exit from a DIFFERENT side or a different point on the same side +- Example: Lambda → AgentCore (`exitX=0.5;exitY=1` bottom), Lambda → Step Functions (`exitX=1;exitY=0.5` right), Lambda → EventBridge (`exitX=1;exitY=0.75` right-lower) +- When 2+ edges enter the same target from the same direction, offset entry points: `entryX=0.25;entryY=0` and `entryX=0.5;entryY=0` (not both at 0.5) + +**Waypoints for non-adjacent routing** (CRITICAL): +- When an edge must route AROUND intervening containers, add explicit waypoints using `` inside the edge's `` +- Create clean L-shaped (2 waypoints) or U-shaped (3 waypoints) paths +- Route waypoints through clear lanes between container rows/columns +- Example: To route from Lambda (right side) around to DynamoDB (below), exit right then create a vertical lane: `exit=(1,0.25)` → waypoint at (x_far_right, y_lambda) → waypoint at (x_far_right, y_dynamo) → enters DynamoDB from right +- See the edge patterns in `references/example-event-driven.drawio` for real examples with 2-3 waypoints per edge + +### Handling Overlaps + +**Always add `labelBackgroundColor=#ffffff`** to every edge label. This prevents labels from blending with crossing edges or nearby icon labels. Include it in the `edgeLabel` style by default — not as an afterthought: +``` +labelBackgroundColor=#ffffff +``` + +Only reroute an edge (via waypoints or different exit/entry points) when the overlap is severe and the reroute is simple and clean — avoid complex rerouting that could make arrows harder to follow. The label zones to be aware of: +- **78px icons**: ~25px label height below the icon (total footprint ~103px tall) +- **48px icons**: ~20px label height below (total footprint ~68px tall) +- **Group labels**: 30px reserved at the top-left of AWS group shapes + +For parallel edges sharing a corridor, offset them by 20px using explicit waypoints and spread connections across different anchor points on the node. + +### Layout Patterns + +- **Top-to-bottom (tiered)**: Best for VPC architectures with user -> LB -> compute -> DB flow +- **Left-to-right (pipeline)**: Best for data pipelines and CI/CD +- **Column-based (reference architecture)**: Best for complex multi-service platforms with labeled columns + +### Step Badges and Legend + +For complex diagrams (7+ services or multiple branching paths): + +**On-diagram badges**: Teal `#007CBD` 28x28 rounded rectangles near arrow source ends. Place at the **source end** of the arrow (NOT midpoint — midpoint is for edge labels). Offset 20px above/left. Minimum 10px clearance from icons and labels. + +**Right sidebar legend**: Panel at `x = diagram_right_edge + 40`, same `y` as title group (y=30). Teal badges (40x38) + bold title + bullet descriptions per step. All step text MUST use `color: light-dark(...)` for dark mode. Increase `mxGraphModel dx` to accommodate sidebar. + +**Legend height MUST match the diagram**: Set `legend-outer` height to span from `y=30` to the bottom of the AWS Cloud group + 20px padding. The legend panel MUST visually extend the full height of the diagram, never shorter. If the diagram bottom is at y=1170, legend height should be ~1160px. + +**Legend MUST NOT cover any diagram elements**: Ensure the legend panel's x position is far enough right that it does not overlap any external actors, service containers, or edges. If there are external actors on the right side (e.g., external APIs), place them to the LEFT of the legend or increase `mxGraphModel dx` to create more space. + +See `references/xml-templates-structure.md` for badge and legend XML. See `references/style-guide.md` for detailed legend rules. + +**Auxiliary/monitoring services**: ONLY CloudWatch, CloudTrail, X-Ray, and IAM are auxiliary. These do NOT get step numbers and do NOT get edges. Place them inside a dedicated **"Auxiliary Services" group** — a dashed, unfilled rectangle (`rounded=0;fillColor=none;dashed=1;verticalAlign=top`) labeled "Auxiliary Services". Placement rules: +- MUST be INSIDE the AWS Cloud boundary (not outside it) +- MUST be in a free corner where it does NOT overlap or interfere with primary services or their edges +- MUST NOT be placed where the legend panel would cover it — if the legend is on the right, place auxiliary at bottom-left +- The dashed box MUST be large enough to contain all auxiliary service containers with padding (at least 20px on all sides) +- Auxiliary service containers MUST use their correct category tint colors (CloudWatch: `#FCE4EC`/`#E7157B`, X-Ray: same, IAM: `#FFEBEE`/`#DD344C`) — NOT gray + +In the legend, add an italic note explaining their role BELOW all step descriptions but ABOVE the Line Styles box — as a separate text element, not inside the Line Styles box. + +**All other services (App Runner, Cognito, Secrets Manager, etc.) are primary services** that MUST have edges connecting them to the data flow and MUST receive step numbers. + +**Decision points**: Maximum 1-2 per diagram. Use `fontStyle=2` (italic) for `[condition]` text on edge labels. Dashed arrows ONLY for failure/fallback paths. + +### Service Placement + +| Service | Correct Container | +|---------|-------------------| +| ALB, NAT Gateway, Bastion | Public subnet | +| EC2, ECS/Fargate, Lambda (VPC), RDS, ElastiCache | Private subnet | +| Transit Gateway, VPN Gateway | VPC level (not in subnet) | +| Route 53, CloudFront, S3, IAM, CloudWatch | Outside VPC | +| Users, On-premises | Outside AWS Cloud boundary | + +**External actor coordinates**: External actors (Users, third-party APIs, on-premises systems) MUST have coordinates that place them visually OUTSIDE the AWS Cloud group rectangle. If the AWS Cloud group spans `(x, y)` to `(x+w, y+h)`, place external actors at `y < y-40` OR `y > y+h+40` OR `x < x-40` OR `x > x+w+40`. Never place external actors inside or overlapping the AWS Cloud boundary. + +## File Naming + +Each diagram gets a **descriptive filename** in kebab-case, placed in `./docs/`. + +| User prompt | Filename | +|---|---| +| "healthcare appointment agent" | `docs/healthcare-appointment-agent.drawio` | +| "3-tier web app in VPC" | `docs/3-tier-vpc-webapp.drawio` | +| "CI/CD pipeline for ECS" | `docs/cicd-ecs-pipeline.drawio` | +| "analyze" (codebase scan) | `docs/-architecture.drawio` | + +Always create a new file unless the user explicitly asks to update an existing diagram. If a name collision occurs, append a number. + +## Output + +1. Create the `docs/` directory if it does not exist +2. Derive the filename from the user's prompt (see File Naming above) +3. **Always create new files** unless the user explicitly asks to update an existing diagram (see Create vs Update above) +4. Save the diagram to `./docs/.drawio` +5. After writing, the PostToolUse hook will automatically: + a. Validate the XML (structure, AWS shapes, edges, geometry) + b. If validation passes, generate a draw.io preview URL +6. If validation fails, fix the errors and rewrite the file +7. **Only after validation passes**, generate the browser preview link by running: + ```bash + python3 ${PLUGIN_ROOT}/scripts/lib/drawio_url.py ./docs/.drawio --open + ``` + This compresses the XML and opens `app.diagrams.net` with the diagram loaded instantly. Do NOT run this if validation failed. +8. If the user requested an export format (png, svg, pdf): + a. Check if draw.io desktop CLI is available + b. Export with `--embed-diagram` to `./docs/.drawio.` + c. Delete the intermediate `.drawio` file on success +9. **Always present to the user**: + - File path + - Diagram type and services included + - Validation status + - The draw.io preview URL (clickable link to open in browser) + - A recommended alt text (concise, under 100 characters, describing the diagram's purpose — not "diagram of...") + +## CRITICAL: XML Well-Formedness + +- **NEVER use double hyphens (`--`) inside XML comments.** `--` is illegal inside `` per the XML spec and causes parse errors. Use single hyphens or rephrase. +- Escape special characters in attribute values: `&`, `<`, `>`, `"` +- Always use unique `id` values for each `mxCell` + +## Important Rules + +- NEVER use compressed/base64 diagram content +- NEVER invent shape names — only use shapes from `references/aws4-shapes.md` +- ALWAYS wrap XML in `` — not bare `` +- ALWAYS include cells id="0" and id="1" as root and default layer +- ALWAYS use `resourceIcon;resIcon=` style for main service icons +- ALWAYS set `container=1;pointerEvents=0;` on group shapes +- ALWAYS validate edge source/target IDs reference existing cells +- ALWAYS include a title block at the top of every diagram +- ALWAYS place 48x48 service icons inside colored category containers +- ALWAYS use `fontFamily=Helvetica;` in every style attribute +- For complex diagrams (7+ services), ALWAYS add step badges and legend +- Use descriptive cell IDs, not random strings (e.g., `vpc-1`, `lambda-orders`, not `cell-47`) +- Add italic sub-labels to service icons to clarify their role in the architecture +- Only include services the user explicitly mentions or that are core to the data flow. Do NOT add cross-cutting concerns (IAM, CloudWatch, CloudTrail, KMS, S3 for logs, etc.) unless the user asks for them — they clutter the diagram and distract from the architecture story +- Include a title/label on the diagram describing the architecture +- ALWAYS set `background="#FFFFFF"` on the mxGraphModel element — AWS guidelines require white background, never transparent +- Do NOT read existing `.drawio` files as reference when generating diagrams — use only the templates and rules in this skill and its references. Reading raw XML examples overloads context and degrades output quality. + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md new file mode 100644 index 00000000..3408b629 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md @@ -0,0 +1,528 @@ +# Diagrams on AWS Documentation + +> Source: AWS internal wiki page "Diagrams on AWS Documentation" (AWS_TCX.Content_Strategy.Content_Quality.graphics.guidelines-diagrams). Last modified by jillx. This extraction preserves all textual content; images are referenced by their original filenames with descriptions derived from surrounding context. + +--- + +## Table of Contents + +- [Purpose](#purpose) +- [Diagrams on the documentation website](#diagrams-on-the-documentation-website) +- [Diagram styling cheat sheet](#diagram-styling-cheat-sheet) +- [Guideline 1. Consider the diagram size and proportion](#guideline-1-consider-the-diagram-size-and-proportion-in-relation-to-the-page-it-will-be-on) +- [Guideline 2. Use background color and padding to create balance and space](#guideline-2-use-background-color-and-padding-to-create-balance-and-space) +- [Guideline 3. Use approved visual foundations to look on-brand and professional](#guideline-3-use-approved-visual-foundations-to-look-on-brand-and-professional) + - [3.1 Visual objects: Icons, illustrations, lines, and shapes](#31-visual-objects-icons-illustrations-lines-and-shapes) + - [3.2 Color](#32-color) + - [3.3 Typography: Fonts, sizes, styles, colors](#33-typography-fonts-sizes-styles-colors) +- [Guideline 4. Double-check your padding, avoid outside borders and shadows](#guideline-4-double-check-your-padding-avoid-outside-borders-and-shadows) +- [Guideline 5. Apply programmatic styles to improve the dark mode experience](#guideline-5-apply-programmatic-styles-to-improve-the-dark-mode-experience) +- [Guideline 6. Be accessible](#guideline-6-be-accessible) +- [Guideline 7. Comply with regional branding requirements](#guideline-7-comply-with-regional-branding-requirements) + - [7.1 Usage of "AWS" in logos](#71-usage-of-aws-in-logos) + - [7.2 Usage of "AWS" in labels and descriptive text](#72-usage-of-aws-in-labels-and-descriptive-text) +- [Need more help? Have suggestions?](#need-more-help-have-suggestions) + +--- + + + +## Purpose + +This page provides visual style guidelines and other best practices (e.g., legal and accessibility compliance) for diagrams on the AWS Documentation website. A diagram creator may apply these best practices regardless of the tool or software used to create style-aligned and compliant diagrams. These guidelines assume little to no background in design. + +For documentation writers and editors seeking step-by-step instructions using specific drawing tools and/or Zonbook integration, see: +- "Create, modify, and add graphics and screenshots" (internal wiki: AWSDocs/editing/graphics/) +- "Add images using zonbook" (internal wiki: AWSDocs/get-started/zonbook-reference/#HAddimages) + +**New to diagrams or the docs team?** We recommend watching the Diagramming 101 training for writers on Broadcast (broadcast.amazon.com/videos/291078). + +**Diagram office hours** are also available if you'd like further collaboration and guidance with your diagram. Sign up via the Documentation Diagramming Office Hours sheet. + +--- + +## Diagrams on the documentation website + +Diagrams help customers understand concepts and processes by providing a visual representation of objects and their relationships. Customers can learn about cross-service relationships, review a task that they are completing, or visualize complex data relationships. Diagrams and other types of visuals can also add visual interest, break up large blocks of text, and increase a customer's affinity towards documentation. (Source: Documentation Getting Started study, insights #3 and #12.) + +Several types of diagrams can help customers understand AWS services and features. Among the categories of diagrams found in documentation, four are the most common: + +### Architecture Diagram + + + +**What is it**: A graphical representation of a set of concepts and objects within an ecosystem. + +**Useful for:** +- Visualizing overall system or application design +- Communicating interconnected and complex relationships across services, features, and their containing contexts (such as VPC, Regions, AZs, etc.) +- Highlighting which part of the overall architecture a service or feature may serve + +### Process/Flow Diagram + + + +**What is it**: A combination of illustrations, connective lines, short facts, and/or labels, that communicates a visual story or overview. + +**Useful for:** +- Presenting a short and simple breakdown of workflows +- Showing users which set of tutorial steps they might be focused on with a given section/page + +### Data Visualization + + + +**What is it:** The visual presentation of data, numbers or facts in a pictorial or graphical format. Data visualizations can help customers understand difficult concepts or identify new patterns. + +**Useful for:** +- Showing the relationship of one or more variables on an output (such as how time and usage impacts cost, how seasonality impacts capacity, etc.) + +**Tip:** Create data visualizations using graphing tools you are comfortable with (Excel, D3, Vega-Lite, etc). + +### Other Conceptual Diagram + + + +**What is it:** A catch-all bucket for other types of diagrams that visually represent relationships within a system. + +**Useful for:** Helping customers visualize and clarify a concept alongside its verbal explanation. + +--- + +## Diagram Styling Cheat Sheet + +Use the following cheat sheet to align your diagram's style with AWS' visual style and language. Does your diagram check off all these element guidelines? + +### Diagram size and proportion + +Try to keep your image mostly visible within a user's viewport and make the text big enough to be readable. Keep images from getting so big as to slow down page loading. Review the sample proportions in Guideline 1 below as a visual starting point. + +Use `scalefit="1"` attribute to prevent large images from spilling over in HTML and PDF. + +### Background color + +Use white (#FFFFFF) in most cases. Do not leave the background transparent. + +### Icons + +**Icons**: Use the most up-to-date icons included in the official AWS architecture icon kit (https://aws.amazon.com/architecture/icons/). If you need an icon that is not available in the kit, consider one of the following: + +1. Submit a SIM to the architecture icon team +2. Use a simple shape, like a rectangle or square with a label inside +3. Reach out to your service UX designer + +**Regional compliance for icons**: Be mindful of using any icons with the terms 'AWS' embedded in the icon to comply with regional requirements. Review Usage of "AWS" in logos in Guideline 7.1 below. + +**Third-party icons**: Generally, you may use 3P technology icons as long as it is accurate and educational. Do not modify another party's icon without their permission. We recommend against using general icons from open-sourced libraries, but if you have a use case that needs it, consult the trademarks team (trademarks@amazon.com) to ensure we have rights to do so. + +**Callouts**: Currently being tested/iterated on updated callout styling and implementation. + +### Lines and arrows + +**Thickness/width:** 1pt for most cases + +**Line styles:** Use **solid lines** for primary connections and containers. Secondary connections and containers can be represented as **dashed lines.** + +**Arrow pointer style:** Open arrow pointers are preferred over closed ones. + + + + +- Arrow with open pointer (preferred) +- Arrow with closed pointer (not preferred) + +### Colors + +Do not modify the colors provided by official icon libraries -- use as is because they contain semantic meaning (e.g., certain colors represent a service category). + +If you need to add additional colors to your diagram, make sure the color values are included within one of the following palettes: + +- The AWS Brand color palette (https://design.amazon.com/styleguide/9188F3F120Af/aws/visual-guidelines/colors/) +- The Polaris (AWS UI) color palette (https://polaris.a2z.com/fundamentals/foundation/colors/) + +### Typography (fonts) + +- **Font:** + - Regular text: Amazon Ember (download from the Typography website if not pre-installed) + - Monospace text: Monaco +- **Weight**: Regular in most cases. Bold can be used for extra emphasis. Do not use Thin or Light (they fail accessibility standards below most diagram-needed font sizes). +- **Size**: 12px +- **Color**: #16191F or #000000 for most icon/illustration labels +- **Additional styling**: *Italics* is preferred over underlines. (In a diagram with arrows/lines, underlines can add unnecessary visual noise.) + +### Labels and text + +**Icon labels:** Center align the label with the icon and place it under the icon. + +**Descriptive text**: Do not embed explanatory text into images -- it is neither accessible nor localizable. Use only short labels for each illustrative object or icon. If you'd like to highlight specific parts of the diagram with explanatory text, use callouts. This is better for accessibility, localization, and regional compliance. + +**Regional compliance for labels/text**: Ensure that usage of the term 'AWS' complies with regional requirements. Review Usage of "AWS" in text in Guideline 7.2 below. + +### Outside framing + +**Padding**: Apply 8px equally to the top, bottom, left, and right of your image. + +**Border**: Do not apply a visible outside border to the diagram, and we recommend staying away from border shadows and fades. + +### Dark mode optimization + +Optimize your image for dark mode by testing out different style attributes. (See Guideline 5 for details.) + +### Accessibility + +Keep most of the text in your documentation, not the graphic. Use alt text when adding your graphic to a guide. (See Guideline 6 for details.) + +### Regional compliance + +Diagrams that display on the China website have to meet the China branding requirements. If your image contains the AWS logo or "AWS" as a term, you have the following options: + +1. Profile out the image that is not compliant, and make appropriate modifications to your text if it refers to an image (low effort, sacrifice customer experience). + - For example, you can add the Region attribute such as ``, which means the image will appear on all doc websites except the China website. For more information, see Region profiling in service doc content. +2. Edit your version of the image to work globally if possible (medium effort, baseline customer experience). +3. Create two different images that comply with each area's legal standards, and profile images accordingly (high effort, optimized customer experience). + +--- + +## Guideline 1. Consider the diagram size and proportion in relation to the page it will be on + +Your decisions about image size and aspect ratio play an important part with overall layout balance and image readability. In the examples below, screens A-G display examples of recommended image size proportions -- the images in each example are fully visible to the user in common browser viewports, and allow the user to stay within the context of what they are learning about by keeping some of the explanatory text in view. Screens H and I exemplify proportions that should be used sparingly, with careful consideration. + + + +--- + +## Guideline 2. Use background color and padding to create balance and space + +Background color and padding settings are very important for images on the documentation website. Please review this section and make sure that your images: + +1. **Have a background color set** -- do **not** save your image with a transparent background +2. **Are saved with an equal amount of padding** to the top, right, bottom, and left of your image (8px in most cases) + +These settings are important to reduce future reliance on programmatic attributes to optimize images. (At dark mode launch, programmatic filters for background, padding, and brightness filter were used to optimize images for dark mode. Moving beyond that, background and padding should be saved within the image itself and reduce the number of dark mode filters to solely brightness filter.) + +### Examples of background and padding issues + +#### Good example -- light mode + + + +**Spacing within the image:** When creating your image, consider your usage of background and white space as part of your overall image. Make sure you leave sufficient "breathing room" space between the objects in your images so that they feel pleasing to look at instead of crammed and uncomfortable. + +**Spacing around the image**: Make sure you leave an even amount of white space to the top, bottom, left, and right of the image. On light mode, this may not be as important because you can rely on the background color of the website to hide any uneven edges. + +However, on dark mode, uneven padding and overlooked backgrounds become very clear. + +#### Bad example -- transparent background in dark mode + + + +**Important**: Make sure you set your background to a color (usually white) before you save. Some imagery software defaults to a transparent background, which can lead to difficult-to-see visual objects and text like shown here. If customers cannot distinguish the shapes or read your image, the image is not acceptable. + +#### Bad example -- no outside padding in dark mode + + + +**Important**: The padding around the main area of your image is also important. In this example, we have a white background, but there is no outside padding. This makes the image feel tight, and the borderlines of the Region container are very hard to distinguish, thus compromising the architectural understandability of the image. + +#### Bad example -- unequal padding (left side only) in dark mode + + + +**Important**: Equal padding around all sides (top, bottom, left, right) of your image is important. In this example, there is padding included on the left, but not to the top, right, or bottom -- which results in an image that looks uneven and lopsided in dark mode. + +#### Bad example -- unequal padding on all sides in dark mode + + + +This is another example of the point mentioned above. In this example, padding is included unequally across all sides, therefore resulting in an image that looks uneven and lopsided in dark mode. + +#### Best practice example -- equal padding on all four sides + + + +**Best practice example:** Equal padding included around all four sides of the main image (8px in most cases) results in an image that looks balanced and intentional in both light and dark modes. + +--- + +## Guideline 3. Use approved visual foundations to look on-brand and professional + +There are several elements that can help make your image look visually aligned to the AWS brand, and to one another as users browse from page to page across user guides: + +1. Use the AWS-aligned visual objects +2. Use brand-approved colors +3. Use consistent and approved type ramp + +### 3.1 Visual objects: Icons, illustrations, lines, and shapes + +Visual objects are used to represent an entity or a concept -- things like an AWS service, AWS in general, user groups, the sun, or the concept of 'forward momentum'. The visual object can range from actually looking like the object (e.g., an image of the sun can have some resemblance to the actual sun) or be very abstracted (e.g., a compute instance may not have a commonly-known or actual physical representation, so we make one up). At AWS, we have mixed ranges of defined visual language and styling applied for categories of concepts. Review the table below to understand the stylistic differences and the best practices for including them in your diagram. + +**Note**: Company/organization logos are also visual objects used on the Documentation website. These should be used sparingly, with approval (by the organization and our internal team) and following the organization's logo usage guidelines. + +#### Category icons, service icons, resource icons + + + +- Make sure you are using the most up-to-date versions of the icons (https://aws.amazon.com/architecture/icons/). The AWS Marketing design team, who manages these icons, updates the icon set on a quarterly basis for Microsoft PowerPoint. While you may find icons in other diagramming tools, they may be outdated. +- Use the light-background version. +- Service icons come in two forms: the Standard service icon and the Alternate service icon. Use the Standard service icons for your diagrams (the Alternate ones will eventually become deprecated). + +#### General icons and illustrations + + + +Use AWS-approved/created general icons and illustrations to keep aligned with AWS visual styling. Using non-approved third-party illustrations may lead to unwanted legal consequences. You can retrieve approved illustrations by: + +- Using the "general icons" from the AWS Icon set (https://aws.amazon.com/architecture/icons/) +- Using the AWS Illustration Library from the AWS brand portal (https://brand.amazon.com/aws/visual-guidelines/illustrations/) +- Submitting a request for a general icon to the AWS Marketing team +- Asking your service designer for assets +- If an illustration you need is unavailable, consider creating your own simple illustration with basic shapes instead + +#### General icons from third party or open-source providers + +Generally, we do not recommend using general icons from third party/open-sourced providers. If you need a generic icon, submit a request to the AWS Marketing team to include it as part of their architecture diagram set. If your use case still requires third party sources, consider the risks of nuanced and downstream trademark/copyright infringement that may occur. We recommend consulting with the AWS Trademark team (trademarks@amazon.com) before using open-sourced icons. + +#### Third-party technology icons/logos + + + +As a general rule, you may use a third party technology icon as part of an educational/referential diagram if that organization has publicly published the icon along with expressed written permissions to use it. + +**Do:** +- Use icons in a way that is truthful and accurate +- Check the 3P's website for published logos/icons and licensing rules +- Review the Customer Reference Finder database for customers who have permitted us to use their logos +- If you are working directly with a company and you ask for permissions via email, save the email + +**Don't:** +- Don't modify styling of 3P icons (e.g., adding borders, adding or changing colors, cropping, scaling disproportionately, adding text, etc.) +- Don't use 3P icons in a way that may suggest an endorsement, affiliation, or sponsorship/co-branding (e.g., combining logos into one logo, implying a relationship between two products) + +#### Basic shapes + + + +- Keep your shapes basic when possible: squares, rectangles, circles, and triangles +- If you're using a square or rectangle, include a 1px border radius (most diagramming/graphics tools should have this setting) +- Shapes that have associated connotations (hearts, crosses, lightning bolts, etc) should be avoided in most cases -- use your best judgement +- Select fill colors from the approved color palettes +- If you are adding a border, keep it at 1px and keep the colors aligned. For example, the "AWS Light" tints of the brand color palette can be used for fills while the regular tints of the colors are used for borderlines. + +#### Lines and arrows + + + +- Keep the width at 1-2px on most diagramming software +- Select colors from the approved color palettes, and make sure the lines are visible +- For arrows, use the line-based, unfilled arrow pointers + +#### Callouts (TBD) + +We are currently testing and iterating on updated callout styling and implementation. Contact the graphics team if you have a use case you want to work through. + +### 3.2 Color + +AWS has two approved color palettes: + +1. **AWS Brand color palette** -- mostly used for illustrations, icons, and banners +2. **AWS Design System color palette (Polaris)** -- mostly used for UI elements (e.g., components and buttons) + +If you are using visual objects (icons and illustrations) from the AWS Marketing library, you will already be using approved colors. If you need to create your own shapes for diagrams and data visualizations, make sure you use colors from one of these two palettes. Most diagramming software will allow you to plug in hex color codes and/or RGB values and/or import color palettes. + +To test AWS colors for contrast accessibility, enter AWS hex color codes into the WebAIM color contrast checker: https://webaim.org/resources/contrastchecker/ + +#### AWS Brand color palette + + + +See the full set, along with hex codes and RGB values, on the AWS Brand website: https://design.amazon.com/styleguide/9188F3F120Af/aws/visual-guidelines/colors/ + +#### AWS Design System (Polaris) color palette + + + +See the full set, along with the hex codes, on the AWS Design System website: https://polaris.a2z.com/fundamentals/foundation/colors/ + +### 3.3 Typography: Fonts, sizes, styles, colors + +Use typography rules consistently within your image and make sure they are large enough to be readable. Aim to keep your text limited to labels and very short descriptions if you absolutely need them. Otherwise, rely on your actual content to explain the image, so that the text can translate to non-English languages and be picked up by assistive technologies. + +#### Font, weight, size, emphasis + +**Regular text:** +- **Font:** Amazon Ember (download from the Typography website: http://typography.aka.amazon.com/fonts/0 if not pre-installed) +- **Weight/style:** Regular, **Bold**, or *Italic*. Stay away from underlines -- the lines can add unnecessary visual noise and introduce room for confusion with connective lines and arrows. +- **Size:** 12px (larger is OK for certain circumstances, but no smaller) + +**Monospace text:** +- **Font:** Use one of the following: **Monaco, Menlo, Consolas, Courier Prime, Courier, Courier New** +- **Weight/style:** Regular or **Bold** +- **Size:** 12px (larger is OK for certain circumstances, but no smaller) + +#### Font color + +- Most text should be **#16191F** or **#000000** (black). +- If you need additional font colors, pick within the approved color set mentioned in the previous section. +- To make text, graphics, and UI components accessible and clearly readable, use the WebAIM contrast checker (https://webaim.org/resources/contrastchecker/) with AWS Brand colors. + +--- + +## Guideline 4. Double-check your padding, avoid outside borders and shadows + +This guideline is a reiteration of Guideline 2. When you finish creating your image and get ready to save, triple-check that you have even padding to the top, left, right, and bottom of the focus of your image. Additionally, make sure that your image software didn't sneak in an unwanted border or outline shadow while saving your image (this sometimes happens). + +#### Non-recommended: Border + + + +Image with non-recommended border surrounding the Region containers. + +#### Non-recommended: Shadow + + + +Image with non-recommended shadow surrounding the Region containers. + +--- + +## Guideline 5. Apply programmatic styles to improve the dark mode experience + +Programmatic styles automatically apply style attributes to your image so they can be optimized when a customer views documentation on dark mode. By default, images have a default style attribute applied to add a white background and 15px padding across the top, bottom, left, and right, as a safety catch-all for images that needed them during the migration to dark mode. To learn more and see step-by-step instructions on how to test these filters, see "Programmatic visual treatments" (internal wiki: AWSDocs/editing/graphics/darkmode/). + +If you're creating a new image and you followed the guidelines on this page, you will most likely use one of the following two style attributes: + +- Use **`bg-padding-filter`** if your image has a white background color +- Use **`notreatment`** if your image has a non-white background color + +--- + +## Guideline 6. Be accessible + +Make sure that your graphics or the concepts that they describe are accessible to customers who use screen readers, or who may have color perception or other vision issues. For more information, see the AWS Style Guide topic on Accessibility (https://alpha-docs-aws.amazon.com/awsstyleguide/latest/styleguide/accessibility.html). + +- Keep text in a graphic limited to labels and callouts. +- Move the workflow description or a short summary of the important concepts to the main content, so that it can be read by a screen reader. +- Avoid mentioning colors. +- Provide enough contrast in the image so that it can be perceived by people with moderately low vision. +- **Add alt text:** + - Write a concise description of the image. Try to keep this description under 100 characters if possible, and avoid repeating text that is already used elsewhere in the content. + > **Note:** For some complex images such as charts or workflow diagrams, a 100-character description might not be adequate to fully convey the content of the image. In this case, ensure that you are providing a more detailed description in the main content of the page, above or below the image. The alt text itself should then concisely describe the *general* content of the image. + - Don't mention the type of image it is, unless the type of image is the point of the content. That's because screen readers already say "Image of" at the beginning of each alt text vocalization. + - Instead of writing "picture of..." or "graphic of..." or "screenshot of...", describe only the main point of the image in relation to the content. + - For something like a workflow diagram, describe the graphic's important elements "as a workflow" or "depicted in a workflow." + - Include terminal punctuation. + - For hyperlinked graphics, include the destination. + +--- + +## Guideline 7. Comply with regional branding requirements + +Any reference to the term "AWS" in any diagram to the audience in Mainland China (docs.amazonaws.cn) needs to be evaluated and modified to follow trademark guidelines. In general, there are two elements that the China branding requirements impact: + +1. Usage of "AWS" in logos +2. Usage of "AWS" in text + +### 7.1 Usage of "AWS" in logos + +Do not use any icons that contain "AWS" if you are planning to publish the diagram on the China site. Commonly, architecture diagrams might include an icon and label to represent AWS and its boundaries within an architecture. You will need to change the icon and the label to comply with the China rebranding. Review the examples below for common examples and resolution options. + +#### Not compliant for the China site + + + +In this image, you see three different styles of AWS cloud icon styling (highlighted with red circles) on three different generations of architecture diagrams. + +#### Compliant for the China site + + + +In this image, you see different approaches to meet the China rebranding requirement: + +- **Option 1:** The AWS Logo icon is completely removed, and its label has changed from "AWS Cloud" to "Amazon Web Services Cloud." +- **Options 2 and 3:** A generic cloud logo is used, fitting with the architecture diagram's overall style. + +If you are using the latest architecture diagram icon set, the generic cloud icon is available in the Architecture Diagram kit (https://aws.amazon.com/architecture/icons/). + +### 7.2 Usage of "AWS" in labels and descriptive text + +Diagrams might contain labels and descriptive text for AWS services, features, and other elements. You may need to change the labels or profile the image out to comply with the China rebrand -- consult the rebranding summary to check if any diagram text or labels need to be modified, and review the compliant examples below. + +#### Labels -- Not compliant + + + +In this image, the container and services include the label "AWS". + +#### Labels -- Compliant options + +**Option 1:** Profile the image out for the China site version of the website, and ensure surrounding text does not include references to an image. + + + +**Option 2:** Create compliant Region-specific versions of the diagram. + + + +**Option 3:** Create a Region-neutral version of the diagram that you can use across all locales by omitting the legal entity of the service/element. To do this, you must ensure that your image is preceded by written text that contains the full service name present in the diagram so you can take advantage of the "subsequent use rule" within the diagram. + + + +**Note:** This option is not valid if your diagram contains a label within the "Important Exceptions" list. In that case, use Option 1 or Option 2. + +#### Descriptive text -- Not compliant + + + +In this image, the term "AWS" is embedded as description text for a corresponding illustration. + +#### Descriptive text -- Compliant options + +**Recommended:** Don't embed explanatory text into images. Use only short labels for each illustrative object or icon. Instead, use callouts to refer to certain aspects of the image you want to describe more with text. This is better for accessibility, localization, and the China rebrand. + +**Alternate option:** Modify the image's embedded text to remove references to "AWS." + +--- + +## Need more help? Have suggestions? + +Leave a comment and/or email aws-doc-graphics@amazon.com and let's discuss! + +--- + +## Image Reference Index + +The following images were referenced in the original document. They are not embedded in this markdown file but are listed here for completeness. Original filenames correspond to the `XWiki_files/` directory of the saved HTML page. + +| Filename | Context / Description | +|---|---| +| `banner-diagrams.png` | Page banner image | +| `Picture1.png` | Architecture diagram example (diagram types table) | +| `process-flow-diagram.png` | Process/flow diagram example (diagram types table) | +| `data-viz.png` | Data visualization example (diagram types table) | +| `example-dg.png` | Other conceptual diagram example (diagram types table) | +| `guides-size.png` | Guideline 1 -- Grid of screens A-I showing recommended vs. not-recommended diagram size proportions within browser viewports | +| `bp-light.png` | Guideline 2 -- Good example: diagram in light mode with proper spacing and padding | +| `bp-d1.png` | Guideline 2 -- Bad example: transparent background in dark mode; objects/text hard to see | +| `bp-d2.png` | Guideline 2 -- Bad example: white background but no outside padding in dark mode | +| `bp-d3.png` | Guideline 2 -- Bad example: unequal padding (left only) in dark mode | +| `bp-d4.png` | Guideline 2 -- Bad example: unequal padding on all sides in dark mode | +| `bp-d5.png` | Guideline 2 -- Best practice: equal 8px padding on all four sides in dark mode | +| `category-service-resource_icons.png` | Guideline 3.1 -- Shows category icons, service icons, and resource icons from the AWS architecture icon kit | +| `general-icons.png` | Guideline 3.1 -- Shows general-purpose AWS icons and illustrations (users, cloud, internet, etc.) | +| `3p-tech.png` | Guideline 3.1 -- Shows third-party technology icons/logos used in diagrams | +| `basic-shapes.png` | Guideline 3.1 -- Shows basic shapes (squares, rectangles, circles) with AWS palette fills and borders | +| `lines-arrows.png` | Guideline 3.1 -- Shows line and arrow style examples (solid, dashed, open/closed pointers) | +| `Screen Shot 2020-12-30 at 11.08.23 AM.png` | Cheat sheet -- Arrow with open pointer (preferred style) | +| `Screen Shot 2020-12-30 at 11.08.28 AM.png` | Cheat sheet -- Arrow with closed pointer (not preferred) | +| `Screen Shot 2021-12-01 at 1.18.59 PM.png` | Guideline 3.2 -- AWS Brand color palette preview | +| `Screen Shot 2020-06-08 at 8.31.54 AM.png` | Guideline 3.2 -- AWS Design System (Polaris) color palette preview | +| `border.png` | Guideline 4 -- Diagram with non-recommended visible border around Region containers | +| `shadow.png` | Guideline 4 -- Diagram with non-recommended shadow around Region containers | +| `Artboard-1.png` | Guideline 7.1 -- Three AWS cloud icon styles that are NOT compliant for China site (highlighted with red circles) | +| `Artboard-2.png` | Guideline 7.1 -- Compliant alternatives: removed AWS logo, changed label, or used generic cloud icon | +| `service-labels.png` | Guideline 7.2 -- Labels not compliant: services labeled with "AWS" prefix | +| `global_china_2.png` | Guideline 7.2 -- Labels Option 1: profile out the image for the China site | +| `global-china_1.png` | Guideline 7.2 -- Labels Option 2: Region-specific diagram versions (global vs. China) | +| `service-labels_option-3.png` | Guideline 7.2 -- Labels Option 3: Region-neutral diagram omitting "AWS" from labels | +| `embedded-text.png` | Guideline 7.2 -- Descriptive text not compliant: "AWS" embedded as description text | +| `logo.png` | Site logo (navigation chrome, not content) | diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws4-shapes.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws4-shapes.md new file mode 100644 index 00000000..b8958472 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws4-shapes.md @@ -0,0 +1,231 @@ +# AWS4 Shape Reference for draw.io + +All shapes use the `mxgraph.aws4.` namespace prefix. Use in style strings as `shape=mxgraph.aws4.{shape_name}`. + +**1040 total shapes** across 31 categories. +Auto-generated from draw.io source (version 2025.1). + +## Service Icons (use `resourceIcon;resIcon=mxgraph.aws4.{name}` style, 78x78) + +### Customer Enablement (fillColor: #3F8624) + +`activate`, `customer_enablement`, `iq`, `managed_services`, `professional_services`, `repost`, `repost_private`, `support`, `training_certification` + +### Business Applications (fillColor: #E7157B) + +`alexa_for_business`, `appfabric`, `business_application`, `chime`, `chime_sdk`, `connect`, `end_user_messaging`, `honeycode`, `pinpoint`, `quick_suite`, `simple_email_service`, `supply_chain`, `wickr`, `workdocs`, `workmail` + +### General (fillColor: #232F3D) + +`all_products`, `general`, `marketplace`, `productIcon`, `resourceIcon` + +### Front End Web Mobile (fillColor: #E7157B) + +`amplify`, `device_farm`, `location_service`, `mobile` + +### Analytics (fillColor: #8C4FFF) + +`analytics`, `athena`, `clean_rooms`, `cloudsearch2`, `data_exchange`, `data_pipeline`, `datazone`, `elasticsearch_service`, `emr`, `entity_resolution`, `finspace`, `glue`, `glue_databrew`, `glue_elastic_views`, `kinesis`, `kinesis_data_analytics`, `kinesis_data_firehose`, `kinesis_data_streams`, `kinesis_video_streams`, `lake_formation`, `managed_service_for_apache_flink`, `managed_streaming_for_kafka`, `quicksight`, `redshift`, `sagemaker_2`, `sql_workbench` + +### Ai Ml (fillColor: #01A88D) + +`apache_mxnet_on_aws`, `app_studio`, `augmented_ai`, `bedrock`, `bedrock_agentcore`, `codeguru_2`, `codewhisperer`, `comprehend`, `comprehend_medical`, `deep_learning_amis`, `deep_learning_containers`, `deepcomposer`, `deeplens`, `deepracer`, `devops_guru`, `elastic_inference_2`, `forecast`, `fraud_detector`, `healthimaging`, `healthlake`, `healthscribe`, `kendra`, `lex`, `lookout_for_equipment`, `lookout_for_metrics`, `lookout_for_vision`, `machine_learning`, `monitron`, `neuron_ml_sdk`, `nova2`, `omics`, `panorama`, `personalize`, `polly`, `q`, `rekognition_2`, `sagemaker`, `sagemaker_ground_truth`, `sagemaker_studio_lab`, `tensorflow_on_aws`, `textract`, `torchserve`, `transcribe`, `translate` + +### Application Integration (fillColor: #E7157B) + +`api_gateway`, `appflow`, `application_integration`, `appsync`, `b2b_data_interchange`, `eventbridge`, `express_workflow`, `managed_workflows_for_apache_airflow`, `mobile_application`, `mq`, `sns`, `sqs`, `step_functions` + +### Management Governance (fillColor: #E7157B) + +`app_config`, `app_wizard`, `application_auto_scaling`, `autoscaling`, `backint_agent`, `chatbot`, `cloudformation`, `cloudtrail`, `cloudwatch_2`, `codeguru`, `config`, `control_tower`, `devops_agent`, `distro_for_opentelemetry`, `license_manager`, `managed_service_for_grafana`, `managed_service_for_prometheus`, `management_and_governance`, `management_console`, `opsworks`, `organizations`, `partner_central`, `personal_health_dashboard`, `proton`, `resilience_hub`, `resource_explorer`, `service_catalog`, `service_management_connector`, `systems_manager`, `systems_manager_incident_manager`, `telco_network_builder`, `trusted_advisor`, `user_notifications`, `well_architect_tool` + +### Networking (fillColor: #8C4FFF) + +`app_mesh`, `application_recovery_controller`, `client_vpn`, `cloud_directory`, `cloud_map`, `cloud_wan`, `cloudfront`, `direct_connect`, `global_accelerator`, `networking_and_content_delivery`, `private_5g`, `route_53`, `rtb_fabric`, `site_to_site_vpn`, `transit_gateway`, `verified_access`, `vpc`, `vpc_lattice`, `vpc_privatelink` + +### Compute (fillColor: #ED7100) + +`sagemaker`, `sagemaker_2`, `sagemaker_model`, `sagemaker_notebook`, `sagemaker_training_job`, `sagemaker_ground_truth`, `rekognition`, `rekognition_image`, `rekognition_video`, `comprehend`, `lex`, `polly`, `translate`, `transcribe`, `textract`, `personalize`, `forecast`, `kendra`, `bedrock`, `bedrock_agentcore`, `codewhisperer`, `healthlake`, `lookout_for_equipment`, `lookout_for_metrics`, `lookout_for_vision`, `monitron`, `panorama`, `devops_guru` + +**AgentCore**: Use `resIcon=mxgraph.aws4.bedrock_agentcore` (NOT `mxgraph.aws4.bedrock`) for Amazon Bedrock AgentCore services (Gateway, Runtime, Memory). See `references/example-agentcore.drawio`. + +## IoT (fillColor: #1A9C37) + +`iot`, `iot_core`, `iot_greengrass`, `iot_analytics`, `iot_events`, `iot_sitewise`, `iot_device_defender`, `iot_device_management`, `iot_things_graph`, `iot_1click`, `iot_button`, `iot_certificate`, `iot_action`, `iot_actuator`, `iot_alexa_enabled_device`, `iot_alexa_skill`, `iot_alexa_voice_service`, `iot_bank`, `iot_bicycle`, `iot_camera`, `iot_car`, `iot_cart`, `iot_coffee_pot`, `iot_desired_state`, `iot_device_gateway`, `iot_dog`, `iot_door_lock`, `iot_factory`, `iot_fire_tv`, `iot_fire_tv_stick`, `iot_generic`, `iot_house`, `iot_http`, `iot_http2`, `iot_lambda`, `iot_lightbulb`, `iot_medical_emergency`, `iot_mqtt`, `iot_over_the_air_update`, `iot_police_emergency`, `iot_policy`, `iot_reported_state`, `iot_rule`, `iot_sensor`, `iot_servo`, `iot_shadow`, `iot_simulator`, `iot_thermostat`, `iot_topic`, `iot_travel`, `iot_utility`, `iot_windfarm`, `freertos`, `iot_device_defender2`, `iot_fleet_hub`, `iot_expresslink`, `iot_fleetwise`, `iot_roborunner`, `iot_twinmaker` +`app_runner`, `auto_scaling2`, `auto_scaling3`, `batch`, `bottlerocket`, `compute`, `compute_optimizer`, `ec2`, `ec2_image_builder`, `elastic_beanstalk`, `elastic_fabric_adapter`, `elastic_load_balancing`, `elastic_vmware_service`, `fargate`, `genomics_cli`, `lambda`, `lightsail`, `lightsail_for_research`, `local_zones`, `nice_dcv`, `nice_enginframe`, `nitro_enclaves`, `outposts`, `outposts_1u_and_2u_servers`, `outposts_family`, `parallel_cluster`, `parallel_computing_service`, `serverless_application_repository`, `simspace_weaver`, `vmware_cloud_on_aws`, `wavelength` + +### Developer Tools (fillColor: #C925D1) + +`application_composer`, `cloud9`, `cloud_control_api`, `cloud_development_kit`, `cloudshell`, `codeartifact`, `codebuild`, `codecatalyst`, `codecommit`, `codedeploy`, `codepipeline`, `codestar`, `command_line_interface`, `corretto`, `developer_tools`, `fault_injection_simulator`, `tools_and_sdks`, `xray` + +### Cloud Financial Management (fillColor: #3F8624) + +`application_cost_profiler`, `budgets_2`, `cost_and_usage_report`, `cost_explorer`, `cost_management`, `custom_billing_manager`, `reserved_instance_reporting`, `savings_plans` + +### Migration Modernization (fillColor: #3F8624) + +`application_discovery_service`, `cloudendure_migration`, `data_transfer_terminal`, `datasync`, `mainframe_modernization`, `migration_and_transfer`, `migration_evaluator`, `migration_hub`, `server_migration_service`, `snowball`, `snowball_edge`, `snowmobile`, `transfer_family`, `transfer_for_sftp`, `transform` + +### End User Computing (fillColor: #ED7100) + +`appstream_20`, `desktop_and_app_streaming`, `worklink`, `workspaces`, `workspaces_family`, `workspaces_thin_client` + +### Ar Vr (fillColor: #E7157B) + +`ar_vr`, `sumerian` + +### Security (fillColor: #DD344C) + +`artifact`, `audit_manager`, `certificate_manager_3`, `cloudhsm`, `cognito`, `detective`, `directory_service`, `firewall_manager`, `guardduty`, `identity_and_access_management`, `inspector`, `key_management_service`, `macie`, `network_firewall`, `payment_cryptography`, `private_certificate_authority`, `resource_access_manager`, `secrets_manager`, `security_agent`, `security_hub`, `security_identity_and_compliance`, `security_incident_response`, `security_lake`, `shield`, `signer`, `single_sign_on`, `verified_permissions`, `waf` + +### Database (fillColor: #C925D1) + +`aurora`, `database`, `database_migration_service`, `documentdb_with_mongodb_compatibility`, `dynamodb`, `elasticache`, `keyspaces`, `managed_apache_cassandra_service`, `memorydb_for_redis`, `neptune`, `oracle_database_at_aws`, `rds`, `rds_on_vmware`, `timestream` + +### Storage (fillColor: #3F8624) + +`backup`, `cloudendure_disaster_recovery`, `efs_infrequentaccess`, `efs_standard`, `elastic_block_store`, `elastic_file_system`, `file_cache`, `fsx`, `fsx_for_lustre`, `fsx_for_netapp_ontap`, `fsx_for_openzfs`, `fsx_for_windows_file_server`, `glacier`, `infrequent_access_storage_class`, `s3`, `s3_on_outposts_storage`, `snowcone`, `storage`, `storage_gateway` + +### Blockchain (fillColor: #ED7100) + +`blockchain`, `managed_blockchain`, `quantum_ledger_database` + +### Quantum Technologies (fillColor: #ED7100) + +`braket`, `quantum_technologies` + +### Contact Center (fillColor: #E7157B) + +`contact_center` + +### Containers (fillColor: #ED7100) + +`containers`, `ecr`, `ecs`, `ecs_anywhere`, `eks`, `eks_anywhere`, `eks_cloud`, `eks_distro`, `red_hat_openshift` + +### Customer Engagement (fillColor: #E7157B) + +`customer_engagement` + +### Media Services (fillColor: #ED7100) + +`deadline_cloud`, `elastic_transcoder`, `elemental`, `elemental_link`, `elemental_mediaconnect`, `elemental_mediaconvert`, `elemental_medialive`, `elemental_mediapackage`, `elemental_mediastore`, `elemental_mediatailor`, `interactive_video`, `media_services`, `nimble_studio`, `thinkbox_deadline`, `thinkbox_draft`, `thinkbox_frost`, `thinkbox_krakatoa`, `thinkbox_sequoia`, `thinkbox_stoke`, `thinkbox_xmesh` + +### Iot (fillColor: #3F8624) + +`freertos`, `greengrass`, `internet_of_things`, `iot_1click`, `iot_analytics`, `iot_button`, `iot_core`, `iot_device_defender`, `iot_device_management`, `iot_edukit`, `iot_events`, `iot_expresslink`, `iot_fleetwise`, `iot_roborunner`, `iot_sitewise`, `iot_things_graph`, `iot_twinmaker` + +### Games (fillColor: #ED7100) + +`gamekit`, `gamelift_2`, `gamelift_streams`, `games`, `gamesparks`, `lumberyard`, `open_3d_engine_2` + +### Satellite (fillColor: #8C4FFF) + +`ground_station`, `satellite` + +### Robotics (fillColor: #ED7100) + +`robomaker`, `robotics` + +### Serverless (fillColor: #ED7100) + +`serverless` + +## Group Shapes (for boundaries) + +`group_account`, `group_auto_scaling_group`, `group_aws_cloud`, `group_aws_cloud_alt`, `group_aws_step_functions_workflow`, `group_corporate_data_center`, `group_ec2_instance_contents`, `group_elastic_beanstalk`, `group_iot_greengrass`, `group_iot_greengrass_deployment`, `group_on_premise`, `group_region`, `group_security_group`, `group_spot_fleet`, `group_vpc2` + +## Sub-Resource Icons (use `shape=mxgraph.aws4.{name}` style, 48x48) + +These are service sub-components from the stencil XML. Use the direct `shape=` style (not `resourceIcon`). + +**Alexa**: `alexa_enabled_device`, `alexa_skill`, `alexa_smart_home_skill`, `alexa_voice_service` + +**Application**: `application_discovery_service_aws_agentless_collector`, `application_discovery_service_aws_discovery_agent`, `application_discovery_service_migration_evaluator_collector`, `application_load_balancer` + +**Aws**: `aws_backup_for_aws_cloudformation`, `aws_backup_legal_hold`, `aws_backup_support_for_amazon_fsx_for_netapp_ontap`, `aws_backup_vault_lock`, `aws_backup_virtual_machine_monitor`, `aws_cloud`, `aws_glue_data_quality`, `aws_glue_for_ray`, `aws_user_notifications` + +**Backup**: `backup_audit_manager`, `backup_aws_backup_support_for_amazon_s3`, `backup_aws_backup_support_for_vmware_workloads`, `backup_backup_plan`, `backup_backup_restore`, `backup_compliance_reporting`, `backup_compute`, `backup_database`, `backup_gateway`, `backup_plan`, `backup_recovery_point_objective`, `backup_recovery_time_objective`, `backup_restore`, `backup_storage`, `backup_vault`, `backup_virtual_machine`, `backup_virtual_machine_monitor` + +**Braket**: `braket_chandelier`, `braket_chip`, `braket_embedded_simulator`, `braket_managed_simulator`, `braket_noise_simulator`, `braket_qpu`, `braket_simulator`, `braket_simulator_1`, `braket_simulator_2`, `braket_simulator_3`, `braket_simulator_4`, `braket_state_vector`, `braket_tensor_network` + +**Checklist**: `checklist_cost`, `checklist_fault_tolerant`, `checklist_performance`, `checklist_security` + +**Cloud**: `cloud_digital_interface`, `cloud_extension_ros`, `cloud_map_resource`, `cloud_wan_segment_network`, `cloud_wan_transit_gateway_route_table_attachment`, `cloud_wan_virtual_pop` + +**Cloudwatch**: `cloudwatch_cross_account_observability`, `cloudwatch_data_protection`, `cloudwatch_evidently`, `cloudwatch_logs`, `cloudwatch_metrics_insights`, `cloudwatch_rum`, `cloudwatch_synthetics` + +**Container**: `container_1`, `container_2`, `container_3`, `container_registry_image` + +**Data**: `data_encryption_key`, `data_exchange_for_apis`, `data_lake_resource_icon`, `data_set`, `data_stream`, `data_table` + +**Datazone**: `datazone_business_data_catalog`, `datazone_data_portal`, `datazone_data_projects` + +**Db**: `db_instance`, `db_instance_read_replica`, `db_instance_standby`, `db_on_instance`, `db_on_instance2` + +**Dynamodb**: `dynamodb_dax`, `dynamodb_standard_access_table_class`, `dynamodb_standard_infrequent_access_table_class`, `dynamodb_stream` + +**Ec2**: `ec2_aws_microservice_extractor_for_net`, `ec2_c6a_instance`, `ec2_c6gn_instance`, `ec2_c6i_instance`, `ec2_c6in_instance`, `ec2_c7g_instance`, `ec2_c7gn_instance`, `ec2_dl1_instance`, `ec2_g5_instance`, `ec2_g5g_instance`, `ec2_hpc6a_instance`, `ec2_hpc6id_instance`, `ec2_i4i_instance`, `ec2_im4gn_instance`, `ec2_inf2_instance`, `ec2_instance_contents`, `ec2_is4gen_instance`, `ec2_m1_mac_instance`, `ec2_m6a_instance`, `ec2_m6i_instance`, `ec2_m6idn_instance`, `ec2_m6in_instance`, `ec2_p4de_instance`, `ec2_r6a_instance`, `ec2_r6i_instance`, `ec2_r6idn_instance`, `ec2_r6in_instance`, `ec2_r7iz_instance`, `ec2_trn1_instance`, `ec2_vt1_instance`, `ec2_x2gd_instance`, `ec2_x2idn_instance`, `ec2_x2iedn_instance`, `ec2_x2iezn_instance` + +**Ecs**: `ecs_copilot_cli`, `ecs_service`, `ecs_service_connect`, `ecs_task` + +**Elastic**: `elastic_block_store_amazon_data_lifecycle_manager`, `elastic_block_store_volume_gp3`, `elastic_file_system_elastic_throughput`, `elastic_file_system_infrequent_access`, `elastic_file_system_intelligent_tiering`, `elastic_file_system_one_zone`, `elastic_file_system_one_zone_infrequent_access`, `elastic_file_system_one_zone_standard`, `elastic_file_system_standard`, `elastic_file_system_standard_infrequent_access`, `elastic_inference`, `elastic_ip_address`, `elastic_network_adapter`, `elastic_network_interface` + +**Elasticache**: `elasticache_for_memcached`, `elasticache_for_redis`, `elasticache_for_valkey` + +**Emr**: `emr_engine`, `emr_engine_mapr_m3`, `emr_engine_mapr_m5`, `emr_engine_mapr_m7` + +**Event**: `event_event_based`, `event_resource`, `event_time_based` + +**Eventbridge**: `eventbridge_custom_event_bus_resource`, `eventbridge_default_event_bus_resource`, `eventbridge_pipes`, `eventbridge_saas_partner_event_bus_resource`, `eventbridge_scheduler`, `eventbridge_schema`, `eventbridge_schema_registry` + +**File**: `file_cache_hybrid_nfs_linked_datasets`, `file_cache_on_premises_nfs_linked_datasets`, `file_cache_s3_linked_datasets`, `file_gateway`, `file_system` + +**Generic**: `generic_application`, `generic_database`, `generic_firewall` + +**Group**: `group_availability_zone`, `group_elastic_load_balancing`, `group_subnet`, `group_vpc` + +**Illustration**: `illustration_desktop`, `illustration_devices`, `illustration_notification`, `illustration_office_building`, `illustration_users` + +**Internet**: `internet_alt1`, `internet_alt2`, `internet_alt22`, `internet_gateway` + +**Iot**: `iot_analytics_channel`, `iot_analytics_data_store`, `iot_analytics_dataset`, `iot_analytics_pipeline`, `iot_core_device_advisor`, `iot_core_device_location`, `iot_device_defender_iot_device_jobs`, `iot_device_gateway`, `iot_device_jobs_resource`, `iot_device_management_fleet`, `iot_device_tester`, `iot_greengrass_artifact`, `iot_greengrass_component`, `iot_greengrass_component_machine_learning`, `iot_greengrass_component_nucleus`, `iot_greengrass_component_private`, `iot_greengrass_component_public`, `iot_greengrass_interprocess_communication`, `iot_greengrass_protocol`, `iot_greengrass_recipe`, `iot_greengrass_stream_manager`, `iot_lorawan_protocol`, `iot_over_the_air_update`, `iot_sailboat`, `iot_sitewise_asset`, `iot_sitewise_asset_hierarchy`, `iot_sitewise_asset_model`, `iot_sitewise_asset_properties`, `iot_sitewise_data_streams`, `iot_thing_freertos_device`, `iot_thing_humidity_sensor`, `iot_thing_industrial_pc`, `iot_thing_plc`, `iot_thing_relay`, `iot_thing_stacklight`, `iot_thing_temperature_humidity_sensor`, `iot_thing_temperature_sensor`, `iot_thing_temperature_vibration_sensor`, `iot_thing_vibration_sensor` + +**Location**: `location_service_geofence`, `location_service_map`, `location_service_place`, `location_service_routes`, `location_service_track` + +**Mainframe**: `mainframe_modernization_analyzer`, `mainframe_modernization_compiler`, `mainframe_modernization_converter`, `mainframe_modernization_developer`, `mainframe_modernization_runtime` + +**Migration**: `migration_hub_refactor_spaces_applications`, `migration_hub_refactor_spaces_environments`, `migration_hub_refactor_spaces_services` + +**Misc**: `action`, `actuator`, `addon`, `agent`, `agent2`, `alarm`, `alert`, `ami`, `application`, `apps`, `archive`, `attribute`, `attributes`, `automation`, `bank`, `bucket`, `budgets`, `bycicle`, `c5a`, `c5ad`, `c5d`, `c6gd`, `camera`, `camera2`, `car`, `cart`, `chat`, `checklist`, `client`, `cloudsearch`, `cloudwatch`, `cluster`, `connector`, `credentials`, `deployment`, `deployments`, `disk`, `document`, `documents`, `documents2`, `documents3`, `echo`, `email`, `endpoint`, `endpoints`, `event`, `factory`, `finding`, `firetv`, `folder`, `folders`, `forums`, `g4dn`, `gamelift`, `gateway`, `gear`, `generic`, `globe`, `house`, `i2`, `i3en`, `inf1`, `inferentia`, `instance`, `instance2`, `instances`, `internet`, `inventory`, `item`, `items`, `layers`, `lightbulb`, `logs`, `m5n`, `mesh`, `message`, `metrics`, `monitoring`, `multimedia`, `mxgraph.aws4`, `namespace`, `notebook`, `nova`, `object`, `peering`, `permissions`, `policy`, `privatelink`, `question`, `queue`, `r5n`, `recover`, `registry`, `rekognition`, `replication`, `rescue`, `resource`, `resources`, `role`, `router`, `rule`, `sensor`, `servers`, `service`, `servo`, `shadow`, `shield2`, `simulation`, `simulator`, `snapshot`, `stack`, `stack2`, `sts`, `table`, `template`, `thermostat`, `topic`, `travel`, `user`, `users`, `utility`, `vault`, `volume`, `windfarm` + +**Network**: `network_access_control_list`, `network_firewall_endpoints`, `network_load_balancer` + +**Opensearch**: `opensearch_dashboards`, `opensearch_ingestion`, `opensearch_observability`, `opensearch_service_cluster_administrator_node`, `opensearch_service_data_node`, `opensearch_service_index`, `opensearch_service_traces`, `opensearch_service_ultrawarm_node` + +**Organizations**: `organizations_account`, `organizations_account2`, `organizations_management_account`, `organizations_management_account2`, `organizations_organizational_unit`, `organizations_organizational_unit2` + +**Rds**: `rds_blue_green_deployments`, `rds_instance`, `rds_instance_alt`, `rds_mariadb_instance`, `rds_mariadb_instance_alt`, `rds_multi_az`, `rds_multi_az_db_cluster`, `rds_mysql_instance`, `rds_mysql_instance_alt`, `rds_optimized_writes`, `rds_oracle_instance`, `rds_oracle_instance_alt`, `rds_piop`, `rds_piops`, `rds_postgresql_instance`, `rds_postgresql_instance_alt`, `rds_proxy`, `rds_proxy_alt`, `rds_sql_server_instance`, `rds_sql_server_instance_alt`, `rds_trusted_language_extensions_for_postgresql` + +**Redshift**: `redshift_auto_copy`, `redshift_data_sharing_governance`, `redshift_ml`, `redshift_query_editor_v20_light`, `redshift_ra3`, `redshift_streaming_ingestion` + +**Route**: `route_53_application_recovery_controller`, `route_53_readiness_checks`, `route_53_resolver`, `route_53_resolver_dns_firewall`, `route_53_resolver_query_logging`, `route_53_routing_controls`, `route_table` + +**S3**: `s3_batch_operations`, `s3_express_one_zone`, `s3_file_gateway`, `s3_multi_region_access_points`, `s3_object_lambda`, `s3_object_lambda_access_points`, `s3_object_lock`, `s3_on_outposts`, `s3_replication_time_control`, `s3_select`, `s3_storage_lens`, `s3_tables`, `s3_vectors` + +**Sagemaker**: `sagemaker_canvas`, `sagemaker_geospatial_ml`, `sagemaker_model`, `sagemaker_notebook`, `sagemaker_shadow_testing`, `sagemaker_train` + +**Simple**: `simple_ad`, `simple_storage_service_directory_bucket`, `simple_storage_service_s3_glacier_instant_retrieval` + +**Systems**: `systems_manager_application_manager`, `systems_manager_change_calendar`, `systems_manager_change_manager`, `systems_manager_compliance`, `systems_manager_distributor`, `systems_manager_opscenter`, `systems_manager_session_manager` + +**Transfer**: `transfer_family_aws_as2`, `transfer_for_ftp_resource`, `transfer_for_ftps_resource`, `transfer_for_sftp_resource` + +**Virtual**: `virtual_gateway`, `virtual_node`, `virtual_private_cloud`, `virtual_router`, `virtual_service`, `virtual_tape_library` + +**Vpc**: `vpc_access_points`, `vpc_carrier_gateway`, `vpc_network_access_analyzer`, `vpc_reachability_analyzer`, `vpc_traffic_mirroring`, `vpc_virtual_private_cloud_vpc` + +**Waf**: `waf_bad_bot`, `waf_bot`, `waf_bot_control`, `waf_labels`, `waf_managed_rule`, `waf_rule` + +**Workspaces**: `workspaces_family_amazon_workspaces`, `workspaces_family_amazon_workspaces_core`, `workspaces_workspaces_web` + +**Other**: `a1_instance`, `access_analyzer`, `ad_connector`, `amplify_aws_amplify_studio`, `athena_data_source_connectors`, `aurora_instance`, `aurora_instance_alt`, `authenticated_user`, `auto_scaling`, `blockchain_resource`, `bucket_with_objects`, `c4_instance`, `c5_instance`, `c5n_instance`, `c6g_instance`, `cache_node`, `cached_volume`, `certificate_manager`, `certificate_manager_2`, `change_set`, `classic_load_balancer`, `cloudfront_functions`, `cloudtrail_cloudtrail_lake`, `coffee_pot`, `cold_storage`, `corporate_data_center`, `corporate_data_center2`, `custom_event_bus_resource`, `customer_gateway`, `d2_instance`, `d3_instance`, `d3en_instance`, `database_migration_workflow_job`, `datasync_discovery`, `default_event_bus_resource`, `dense_compute_node`, `dense_storage_node`, `desired_state`, `development_environment`, `devops_guru_insights`, `documentdb_elastic_clusters`, `door_lock`, `download_distribution`, `edge_location`, `eks_on_outposts`, `email_2`, `email_notification`, `encrypted_data`, `external_sdk`, `external_toolkit`, `f1_instance`, `filtering_rule`, `firetv_stick`, `fleet_management`, `flow_logs`, `fsx_file_gateway`, `g3_instance`, `g4ad_instance`, `game_tech`, `game_tech2`, `gateway_load_balancer`, `general_access_points`, `git_repository`, `glacier_deep_archive`, `global_secondary_index`, `glue_crawlers`, `glue_data_catalog`, `h1_instance`, `habana_gaudi`, `hardware_board`, `hdfs_cluster`, `high_memory_instance`, `hosted_zone`, `http2_protocol`, `http_notification`, `http_protocol`, `i3_instance`, `identity_access_management_iam_roles_anywhere`, `import_export`, `instance_with_cloudwatch`, `instance_with_cloudwatch2`, `instances_2`, `intelligent_tiering`, `json_script`, `key_management_service_external_key_store`, `lambda_function`, `license_manager_application_discovery`, `license_manager_license_blending`, `long_term_security_credential`, `m4_instance`, `m5_instance`, `m5a_instance`, `m5d_instance`, `m5dn_instance`, `m5n_instance`, `m5zn_instance`, `m6g_instance`, `m6gd_instance`, `mac_instance`, `magnifying_glass`, `magnifying_glass_2`, `maintenance_windows`, `managed_ms_ad`, `management_console2`, `mediaconnect_gateway`, `medical_emergency`, `mfa_token`, `mobile_client`, `mobile_hub`, `mq_broker`, `mqtt_protocol`, `ms_sql_instance`, `ms_sql_instance_alternate`, `msk_amazon_msk_connect`, `multiple_volumes_resource`, `mysql_db_instance`, `mysql_db_instance_alternate`, `nat_gateway`, `non_cached_volume`, `office_building`, `one_zone_ia`, `open_3d_engine`, `opsworks_apps`, `opsworks_permissions`, `optimized_instance`, `oracle_db_instance`, `oracle_db_instance_alternate`, `p2_instance`, `p3_instance`, `p3dn_instance`, `p4_instance`, `p4d_instance`, `parameter_store`, `patch_manager`, `permissions_2`, `pinpoint_journey`, `police_emergency`, `postgresql_instance`, `programming_language`, `quicksight_paginated_reports`, `r4_instance`, `r5_instance`, `r5a_instance`, `r5ad_instance`, `r5b_instance`, `r5d_instance`, `r5gd_instance`, `r5n_instance`, `r6g_instance`, `rdn_instance`, `rekognition_image`, `rekognition_video`, `replication_time_control`, `reported_state`, `rule_2`, `rule_3`, `run_command`, `saas_event_bus_resource`, `saml_token`, `search_documents`, `security_group`, `security_hub_finding`, `shield_shield_advanced`, `source_code`, `spot_instance`, `sql_primary`, `sql_replica`, `ssl_padlock`, `standard_ia`, `state_manager`, `streaming_distribution`, `sts_alternate`, `t2_instance`, `t3_instance`, `t3a_instance`, `t4g_instance`, `tape_gateway`, `tape_storage`, `temporary_security_credential`, `textract_analyze_lending`, `topic_2`, `traditional_server`, `trainium_instance`, `transit_gateway_attachment`, `volume_gateway`, `vpn_connection`, `vpn_gateway`, `well_architected_tool`, `work_package`, `x1_instance`, `x1_instance2`, `x1e_instance`, `z1d_instance` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md new file mode 100644 index 00000000..fd3ceabd --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md @@ -0,0 +1,49 @@ +# draw.io CLI Export Reference + +The draw.io desktop app includes a CLI for exporting diagrams to PNG, SVG, or PDF. + +## Locating the CLI + +Try `drawio` first (works if on PATH), then fall back to platform-specific path: + +- **macOS**: `/Applications/draw.io.app/Contents/MacOS/draw.io` +- **Linux**: `drawio` (typically on PATH via snap/apt/flatpak) +- **Windows**: `"C:\Program Files\draw.io\draw.io.exe"` + +Use `which drawio` (or `where drawio` on Windows) to check PATH first. + +## Export Command + +```bash +drawio -x -f -e -b 10 -o +``` + +Key flags: +- `-x` / `--export`: export mode (required) +- `-f` / `--format`: output format (png, svg, pdf) +- `-e` / `--embed-diagram`: embed diagram XML in the output (remains editable in draw.io) +- `-o` / `--output`: output file path +- `-b` / `--border`: border width (default: 0, use 10) +- `-t` / `--transparent`: transparent background (PNG only) +- `-s` / `--scale`: scale the diagram size +- `--width` / `--height`: fit into specified dimensions (preserves aspect ratio) +- `-a` / `--all-pages`: export all pages (PDF only) +- `-p` / `--page-index`: select a specific page (0-based) + +## Supported Formats + +| Format | Embed XML | Notes | +|--------|-----------|-------| +| `png` | Yes (`-e`) | Viewable everywhere, editable in draw.io | +| `svg` | Yes (`-e`) | Scalable, editable in draw.io | +| `pdf` | Yes (`-e`) | Printable, editable in draw.io | + +## File Naming + +Use double extensions: `architecture.drawio.png`, `architecture.drawio.svg`, `architecture.drawio.pdf`. This signals the file contains embedded diagram XML. Opening in draw.io recovers the editable diagram. After a successful export, delete the intermediate `.drawio` file since the exported file contains the full diagram. + +## Opening the Result + +- **macOS**: `open ` +- **Linux**: `xdg-open ` +- **Windows**: `start ` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-advanced.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-advanced.md new file mode 100644 index 00000000..50c82cd0 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-advanced.md @@ -0,0 +1,50 @@ +# Diagram Templates — Advanced + +Multi-region, hybrid, and sizing guidelines. See `diagram-templates-basic.md` for basic patterns. + +## Multi-Region Active-Active + +``` +Layout (two regions side by side): + [Route 53 (latency-based routing)] at top + + [Region 1: us-east-1] [Region 2: eu-west-1] + [CloudFront] [CloudFront] + [ALB] [ALB] + [ECS/Lambda] [ECS/Lambda] + [Aurora (primary)] ←──replication──→ [Aurora (replica)] + [DynamoDB Global Table] ←──sync──→ [DynamoDB Global Table] + [S3] ←──replication──→ [S3] + + [Global Accelerator] optionally at top +``` + +## Hybrid Architecture (On-Premises + AWS) + +``` +Layout: + [Corporate Data Center] + [Traditional Server] + [Database] + [Active Directory] + + ←── [Direct Connect] / [Site-to-Site VPN] ──→ + + [AWS Cloud] + [Transit Gateway] + [VPC - Production] + [workloads] + [VPC - Shared Services] + [Directory Service] + [Systems Manager] + [VPC - Development] + [workloads] +``` + +## Sizing Guidelines for Templates + +- **Small diagram** (3-5 services): pageWidth=800, pageHeight=600 +- **Medium diagram** (6-12 services): pageWidth=1169, pageHeight=827 (default A3) +- **Large diagram** (13+ services): pageWidth=1600, pageHeight=1200 +- **Multi-region**: pageWidth=2000, pageHeight=1000 +- **Complex VPC**: pageWidth=1400, pageHeight=1000 diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md new file mode 100644 index 00000000..96562022 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md @@ -0,0 +1,111 @@ +# Diagram Templates — Basic + +Ready-to-use patterns for common AWS architectures. Use these as starting points. + +## Serverless Web Application + +Services: CloudFront → API Gateway → Lambda → DynamoDB, with S3 for static assets and Cognito for auth. + +``` +Layout (left to right): + [Users] → [CloudFront] → [S3 Bucket (static)] + → [API Gateway] → [Lambda] → [DynamoDB] + → [S3 Bucket (data)] + [Cognito] connected to [API Gateway] (auth) +``` + +Typical cell arrangement: +- Users icon at x=50 +- CloudFront at x=250 +- S3 static at x=450, y offset up +- API Gateway at x=450 +- Lambda at x=650 +- DynamoDB at x=850 +- Cognito at x=450, y offset down + +## VPC with Public/Private Subnets + +``` +Layout (nested groups): + [AWS Cloud] + [Region] + [VPC 10.0.0.0/16] + [AZ-1] + [Public Subnet 10.0.1.0/24] + - NAT Gateway + - ALB + [Private Subnet 10.0.2.0/24] + - EC2 / ECS instances + - RDS (primary) + [AZ-2] + [Public Subnet 10.0.3.0/24] + - NAT Gateway + [Private Subnet 10.0.4.0/24] + - EC2 / ECS instances + - RDS (standby) + [Internet Gateway] at VPC boundary + [Users] → [Internet Gateway] → [ALB] → [EC2/ECS] +``` + +## Microservices on ECS/EKS + +``` +Layout: + [Route 53] → [CloudFront] → [ALB] + + [VPC] + [ECS/EKS Cluster] + [Service A] ←→ [Service B] ←→ [Service C] + + [ElastiCache] connected to services + [RDS Aurora] connected to services + + [ECR] connected to [ECS/EKS Cluster] + [CloudWatch] monitoring all services +``` + +## Data Pipeline / Analytics + +``` +Layout (left to right, pipeline flow): + [Data Sources] + - [Kinesis Data Streams] ← external data + - [S3 Bucket (raw)] ← batch uploads + + [Processing] + - [Kinesis Data Firehose] → [S3 (processed)] + - [Glue ETL Jobs] → [S3 (curated)] + - [Lambda] for real-time transforms + + [Storage] + - [S3 Data Lake] (multiple buckets) + - [Glue Data Catalog] + + [Analytics] + - [Athena] → queries S3 + - [Redshift] → warehouse + - [QuickSight] → dashboards + + [Lake Formation] governing access across the pipeline +``` + +## CI/CD Pipeline + +``` +Layout (left to right, pipeline stages): + [CodeCommit/GitHub] → [CodeBuild] → [CodeDeploy] → [Target] + + Detailed: + [Developer] → [CodeCommit] + [CodeCommit] → [CodePipeline] + [CodePipeline] → [CodeBuild (build)] + [CodeBuild] → [S3 (artifacts)] + [CodePipeline] → [CodeBuild (test)] + [CodePipeline] → [CodeDeploy (staging)] + [CodePipeline] → [Manual Approval] + [CodePipeline] → [CodeDeploy (production)] + + [ECR] if deploying containers + [CloudWatch] monitoring pipeline + [SNS] for notifications +``` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-agentcore.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-agentcore.drawio new file mode 100644 index 00000000..ec269a48 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-agentcore.drawio @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-complex-platform.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-complex-platform.drawio new file mode 100644 index 00000000..e32d5aba --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-complex-platform.drawio @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-diagrams.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-diagrams.md new file mode 100644 index 00000000..3c7164ee --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-diagrams.md @@ -0,0 +1,803 @@ +# Example Diagrams + +Annotated XML samples from real AWS architecture diagrams. Use these as references for style, layout, and structure. + +## Example 1: OpenSearch Trending Queries (Pipeline Layout) + +**Architecture type**: Left-to-right data pipeline with Step Functions workflow group +**Key patterns**: Pipeline flow, Step Functions container, sub-resource icons (crawlers, catalogs), edge labels as child cells + +### Prompt + +Generate this diagram that shows a serverless architecture for identifying trending search queries, where user search logs flow through an API Gateway and streaming pipeline into S3, get processed and clustered by batch ETL jobs on a daily schedule, and then use an LLM to pick the most relevant trending query per cluster to display back on the search page. The system should include a real-time ingestion path with streaming and buffering, a batch processing path with crawlers and transformation jobs orchestrated by a scheduler, and a serving layer with a NoSQL database and API for surfacing trending queries to both end users and business analysts. + +### Full XML + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### Notable patterns + +- **Step Functions workflow as container**: The main batch orchestration is wrapped in a `group_aws_step_functions_workflow` container (850x640px, ID `o_v1HXyxiM5dD5V4Gu-O-15`) with `container=1` and `pointerEvents=0`. All workflow steps (S3, Glue, Athena, DynamoDB) are children of this group with relative coordinates inside the 640px-wide workflow boundary. +- **Sub-resource icons positioned above service icons**: Glue Crawlers (48x48px, `shape=mxgraph.aws4.glue_crawlers`) and Glue Data Catalogs (38x41px, `shape=mxgraph.aws4.glue_data_catalog`) are positioned directly above their associated S3 buckets or Glue services, creating visual sub-component relationships without explicit parent-child XML nesting. +- **Edge labels as child cells with connectable=0**: Three edges include inline text labels using child `mxCell` elements with `connectable="0"` and `style="edgeLabel;..."` (e.g., "query logs", "user query", "invoke"). The `relative="1"` geometry positions them along the edge path using offset coordinates. +- **Bidirectional edge with startArrow=open**: The Lambda-to-Bedrock connection (ID `o_v1HXyxiM5dD5V4Gu-O-32`) uses `startArrow=open;startFill=0` to show a two-way invocation pattern, distinguishing the LLM request-response flow from unidirectional data flows. +- **EventBridge split into service + scheduler**: EventBridge uses two nodes: the main service icon (`resIcon=mxgraph.aws4.eventbridge`) and a separate EventBridge Scheduler sub-resource (`shape=mxgraph.aws4.eventbridge_scheduler`), connected sequentially to show schedule-driven Step Functions invocation. +- **Feedback loop with complex routing**: DynamoDB output (ID `o_v1HXyxiM5dD5V4Gu-O-33`) routes back to a Lambda (ID `o_v1HXyxiM5dD5V4Gu-O-39`) and then to API Gateway using a long edge with three `mxPoint` waypoints (1210,469 → 1210,550 → 437,550), creating a U-shaped return path that avoids crossing the forward pipeline. +- **Text-only annotation nodes**: Two plain text cells (IDs `o_v1HXyxiM5dD5V4Gu-O-48`, `o_v1HXyxiM5dD5V4Gu-O-49`) with `style="text;html=1;...strokeColor=none;fillColor=none"` provide "Search query" and "content analysis" labels near actors, demonstrating how to add non-editable descriptive text outside the service icon paradigm. + +## Example 2: Bedrock AgentCore Healthcare Agent (Compact Layout) + +**Architecture type**: Compact agent-based architecture with AWS Cloud group +**Key patterns**: Actor shape for user, OAuth bidirectional edges with waypoints, text annotations for flow descriptions, tool call list boxes + +### Prompt + +Generate this diagram that shows the architecture of an AI-powered healthcare appointment agent where a user interacts through a conversational interface backed by Amazon Bedrock AgentCore Gateway, which connects to MCP tools exposed via OpenAPI specs, with authentication/identity management on one side and a FHIR-compliant health data store on the other. Include the flow from user authentication through the agent's decision-making to the backend services that handle immunization records, schedules, and appointment booking. + +### Full XML + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### Notable patterns + +- **Actor shape for user**: A `shape=actor` element (id `dGBQkeyt1rKohwzD1Iis-1`) positioned outside the AWS Cloud group at x="40" y="180" represents the external user, creating clear visual separation between the user and cloud infrastructure. + +- **Rectangle container for agent component**: The agent is represented by a plain rectangle container (id `dGBQkeyt1rKohwzD1Iis-8`, 180x140px) with a text label overlay reading "Strands or Langgraph Agent" (id `dGBQkeyt1rKohwzD1Iis-9`) and a healthcare agent icon (id `dGBQkeyt1rKohwzD1Iis-7`) placed inside it, demonstrating how to create labeled component groupings. + +- **Bidirectional dashed edges with open arrows**: OAuth flows use `dashed=1` edges with `startArrow=open;startFill=0;endArrow=open;endFill=0` to show bidirectional communication. The edges connect Cognito (id `dGBQkeyt1rKohwzD1Iis-4`) to both the agent container and AgentCore Identity (id `dGBQkeyt1rKohwzD1Iis-11`), and from AgentCore Gateway to API Gateway. + +- **labelBackgroundColor=#ffffff on edges**: All OAuth flow edges set `labelBackgroundColor=#ffffff` to ensure edge labels remain readable when crossing other elements or backgrounds, preventing visual clutter. + +- **Tool call boxes with evenly spaced rectangles**: Four tool boxes are created as plain rectangles (height=30, width=210) at y-coordinates 190, 230, 270, 310 (40px intervals), each with an overlaid text cell containing the tool name. This pattern creates a clean vertical list without complex nesting. + +- **Text annotations near edges**: Flow descriptions like "Invokes LLM and processes outputs" (id `dGBQkeyt1rKohwzD1Iis-17`), "Agent response" (id `dGBQkeyt1rKohwzD1Iis-15`), and "oAuth 2.0 Ingress" (id `dGBQkeyt1rKohwzD1Iis-19`) are positioned as separate text cells near their respective edges, using fontSize=11 for readability without overwhelming the diagram. + +- **Waypoint routing to avoid label overlap**: The edge from AgentCore Identity (id `dGBQkeyt1rKohwzD1Iis-22`) routes vertically upward using a waypoint at (416.63, 196) to avoid overlapping the "AgentCore Gateway" label, demonstrating explicit control over edge paths in dense layouts. + +## Example 3: Amazon DataZone Unified Data Catalog (Column Layout) + +**Architecture type**: Column-based reference architecture with nested groups +**Key patterns**: Dense layout with 40px icons and fontSize=11, multiple container nesting levels, external data source icons, dashed column groupings + +### Prompt + +Generate this diagram that shows a unified data catalog architecture on AWS where data from various sources gets ingested, stored in data lakes and warehouses, and automatically cataloged with metadata. Amazon DataZone acts as the central hub where all metadata is organized, enriched with business context, and made discoverable. Users access a self-service portal to find, share, and govern data assets across the organization. + +### Full XML + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### Notable patterns + +- **Four-column layout with dashed borders**: Left column (Data sources) outside AWS Cloud, three internal columns (Data ingestion, Data storage, DataZone domain) inside AWS Cloud, all separated by `dashed=1` rectangles +- **Dense vertical stacking with 40px icons**: Data ingestion column shows 5 services (AppFlow, Glue, DMS, Kinesis, MSK) vertically stacked at 40px height with `fontSize=11` labels below +- **Multiple nesting levels**: DataZone domain contains domain unit box, which contains projects box, which contains dashed "Inventory enrichment" box with 25px sub-resource icons +- **External data source icons**: Left column uses non-AWS generic icons (cylinder for databases, building for on-premises, video player, file icons) to represent sources outside AWS +- **Service-level vs sub-resource shapes**: Main services use `shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.{name}` style (40px), enrichment icons use direct `shape=mxgraph.aws4.{name}` (25px) +- **Italic/bold typography for hierarchy**: Section headers use regular weight, italic text for sub-labels (e.g., "data warehouse"), bold for final summary label ("Unified data catalog") +- **Open arrow edges without labels**: All connections use `endArrow=open;endFill=0` style with no edge labels, keeping visual noise minimal in this dense diagram diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-event-driven.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-event-driven.drawio new file mode 100644 index 00000000..cb3bfd69 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-event-driven.drawio @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-microservices.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-microservices.drawio new file mode 100644 index 00000000..bcf1a22a --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-microservices.drawio @@ -0,0 +1,370 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-multi-region-active-active.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-multi-region-active-active.drawio new file mode 100644 index 00000000..27351ee2 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-multi-region-active-active.drawio @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-saas-backend.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-saas-backend.drawio new file mode 100644 index 00000000..19d871ec --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-saas-backend.drawio @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-sketch.drawio b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-sketch.drawio new file mode 100644 index 00000000..a1798595 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/example-sketch.drawio @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md new file mode 100644 index 00000000..339efe1d --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md @@ -0,0 +1,78 @@ +# AWS Group and Edge Style Templates + +Complete style strings for draw.io AWS group shapes and edge types. Copy directly into `style=` attributes. + +## AWS Cloud +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=light-dark(#232F3E0D,#232F3E0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#232F3E;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Region + +**CRITICAL**: Region MUST use `container=0` (NOT `container=1`). Services are placed at `parent="1"` (root) with absolute coordinates positioned VISUALLY inside the region rectangle. This prevents nesting depth issues that break edge auto-routing. + +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=14;fontStyle=1;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_region;strokeColor=#00A4A6;fillColor=light-dark(#0C7B7D0D,#0C7B7D0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#00A4A6;dashed=1;container=0;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Availability Zone +``` +fillColor=none;strokeColor=#147EBA;dashed=1;verticalAlign=top;fontStyle=0;fontColor=#147EBA;whiteSpace=wrap;html=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## VPC +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=light-dark(#8C4FFF0D,#8C4FFF0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#8C4FFF;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Public Subnet +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=light-dark(#2488140D,#2488140D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#248814;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Private Subnet +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=light-dark(#147EBA0D,#147EBA0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#147EBA;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Security Group +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_security_group;strokeColor=#DD3522;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#DD3522;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Auto Scaling Group +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_auto_scaling_group;strokeColor=#ED7100;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#ED7100;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Account +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_account;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Step Functions Workflow +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_step_functions_workflow;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0 +``` + +## Edge Styles + +### Standard directional +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0 +``` + +### Bidirectional +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=block;startFill=1;endFill=1;strokeColor=#545B64;rounded=0 +``` + +### Dashed (async/optional) +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0;dashed=1 +``` + +### Open arrow (data flow) +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=open;elbow=vertical;startArrow=none;endFill=0;strokeColor=#545B64;rounded=0 +``` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/post-processing.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/post-processing.md new file mode 100644 index 00000000..f25f7d86 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/post-processing.md @@ -0,0 +1,11 @@ +# Post-Processing Pipeline + +Deterministic fixers run automatically via the `validate-drawio.sh` PostToolUse hook, in this order: + +1. **fix_nesting.py** — Sets Region `container=0`, re-parents children to root +2. **fix_icon_colors.py** — Corrects service icon fillColor to match category +3. **fix_step_badges.py** — Nudges overlapping step badges apart +4. **fix_placement.py** — Moves external actors below the title block (y >= 140) +5. **fix_legend_size.py** — Resizes legend panel to match diagram height + +All scripts are in `scripts/lib/`. The pipeline is orchestrated by `scripts/lib/post_process_drawio.py`, which chains them in sequence. No manual invocation is needed when using the PostToolUse hook. diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md new file mode 100644 index 00000000..f88a6ed5 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md @@ -0,0 +1,99 @@ +# AWS Reference Architecture Style Guide + +Style rules and visual standards. For XML code blocks, see `xml-templates-structure.md` and `xml-templates-examples.md`. + +**Primary visual references**: `example-multi-region-active-active.drawio`, `example-event-driven.drawio`, `example-microservices.drawio`, and `example-saas-backend.drawio` demonstrate all patterns below. + +## Title + Subtitle Block + +Every diagram MUST have a title group: title (30px bold), subtitle (16px), orange separator (`strokeColor=#FF9900`). Title = architecture name, subtitle = what it does. Width MUST span the full diagram. See `xml-templates-structure.md` for XML. + +## Dark/Light Adaptive Contrast + +| Element | Property | Value | +|---------|----------|-------| +| AWS Cloud fills | `fillColor` | `light-dark(#232F3E0D,#232F3E0D)` | +| Region fills | `fillColor` | `light-dark(#0C7B7D0D,#0C7B7D0D)` | +| VPC fills | `fillColor` | `light-dark(#8C4FFF0D,#8C4FFF0D)` | +| Public subnet fills | `fillColor` | `light-dark(#2488140D,#2488140D)` | +| Private subnet fills | `fillColor` | `light-dark(#147EBA0D,#147EBA0D)` | +| Users container stroke | `strokeColor` | `light-dark(#666666,#D4D4D4)` | +| Legend background | `fillColor` | `light-dark(#EDF3FF,#305363)` | +| Legend step text | inline CSS | `color: light-dark(rgb(0,0,0), rgb(255,255,255))` | +| Line Styles box | `fillColor` | `light-dark(#F5F5F5,#29393B)` | + +**Hex+alpha**: `#0C7B7D0D` = teal at ~5% opacity (last two hex digits are alpha). Add `fillStyle=auto;` when using `light-dark()` fills. + +## Users Container + +Users and external actors MUST be wrapped in a visible container for dark mode. See `xml-templates-structure.md` for XML. + +- Container `fillColor=#f5f5f5` provides contrast in dark mode +- `strokeColor=light-dark(#666666,#D4D4D4)` adapts to mode +- Icon `value=""` (empty) since the container carries the label +- Shadow enabled for visual depth + +## Right Sidebar Step Legend + +Legend panel positioned to the RIGHT of the main diagram. See `xml-templates-structure.md` for XML. + +- Position: `x = diagram_right_edge + 40`, same `y` as title group +- Panel width: ~650px, adaptive background `light-dark(#EDF3FF,#305363)` +- Step entries: teal badge (40x38) at left + text block (width ~548) at x=52 +- Each step `` MUST include `color: light-dark(rgb(0,0,0), rgb(255,255,255))` +- Badge style: `strokeColor=default;strokeWidth=2;shadow=1;glass=0` +- Stack entries vertically with ~10px gap + +## Step Number Badges (On-Diagram) + +Small teal `#007CBD` badges (28x28, fontSize=16) placed near arrows. See `xml-templates-structure.md` for XML. + +- Place near arrow source end, offset 20px above/left +- Minimum clearance: 10px from any icon, container edge, or edge label +- Style: `strokeColor=default;strokeWidth=2;shadow=1;glass=0` + +## Service Group Containers + +### Category Tint Colors + +| Category | fillColor (tint) | strokeColor | Example Services | +|----------|-------------------|-------------|-----------------| +| Compute | `#FFF2E8` | `#ED7100` | Lambda, EC2, ECS, Fargate | +| Database | `#F5E6F7` | `#C925D1` | DynamoDB, RDS, Aurora | +| Analytics/Networking | `#EDE7F6` | `#8C4FFF` | API Gateway, VPC, CloudFront, Kinesis | +| Storage | `#E8F5E9` | `#3F8624` | S3, EBS, EFS | +| App Integration | `#FCE4EC` | `#E7157B` | EventBridge, SQS, SNS, Step Functions | +| AI/ML | `#E0F2F1` | `#01A88D` | SageMaker, Bedrock | +| Security | `#FFEBEE` | `#DD344C` | IAM, Cognito, WAF, KMS | +| IoT | `#E8F5E9` | `#1A9C37` | IoT Core, Greengrass, IoT Analytics | +| General/Auxiliary | `#F5F5F5` | `#666666` | CloudWatch, auxiliary services | + +Container 120x120, icon 48x48 at (x=36, y=30). See `xml-templates-structure.md` for XML. + +## Group Shapes with Adaptive Fills + +Region: `light-dark(#0C7B7D0D,#0C7B7D0D)` / `#00A4A6`. VPC: `light-dark(#8C4FFF0D,#8C4FFF0D)` / `#8C4FFF`. Public subnet: `light-dark(#2488140D,#2488140D)` / `#248814`. Private subnet: `light-dark(#147EBA0D,#147EBA0D)` / `#147EBA`. Add `fillStyle=auto;` when using `light-dark()` fills. + +## Font Standard + +**Default mode**: `fontFamily=Helvetica`. **Sketch mode**: `fontFamily=Comic Sans MS`. Do NOT use Amazon Ember or other fonts. + +Font size hierarchy: +- Title: 30px bold | Subtitle: 16px | Group titles: 14px bold | Container labels: 12px bold | Service labels: 10px | Edge labels: 11px | Legend badge: 22px bold (legend) / 16px bold (on-diagram) | Legend text: 14px + +## Sketch Mode + +Add `sketch=1;curveFitting=1;jiggle=2` to all non-icon elements. Keep `sketch=0` on service icons. See `example-sketch.drawio`. + +| Element | Default | Sketch | +|---------|---------|--------| +| Font | Helvetica | Comic Sans MS | +| Container fills | static tint | `light-dark(LIGHT_TINT,#000000)` | +| Icon label text | `fontColor=#232F3E` | `` | +| Users container | `fillColor=#f5f5f5` | `fillColor=light-dark(#F5F5F5,#000000);fontColor=light-dark(#333333,#FAFAFA)` | +| Badge number text | `fontColor=#FFFFFF` | `` | +| Legend badge | `fontColor=#FFFFFF` | `fontColor=light-dark(#000000,#121212)` | + +## AgentCore Icons + +Use `resIcon=mxgraph.aws4.bedrock_agentcore` (NOT `mxgraph.aws4.bedrock`) for Amazon Bedrock AgentCore services. See `example-agentcore.drawio`. diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md new file mode 100644 index 00000000..d96dabca --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md @@ -0,0 +1,193 @@ +# draw.io XML Structure Reference + +## File Structure + +A `.drawio` file is native mxGraphModel XML. Always generate XML directly. + +```xml + + + + + + + + + + + +``` + +- The `` and `` wrappers are required — never use bare `` +- Cell `id="0"` is the root layer +- Cell `id="1"` is the default parent layer +- All diagram elements use `parent="1"` unless using containers + +## Cell Types + +### Vertex (Shape/Icon) +```xml + + + +``` + +### Edge (Connector) +```xml + + + +``` + +### Group (Container) + +Groups MUST have `container=1` in style. Children set `parent` to the group's ID and use **relative coordinates**. + +```xml + + + + + + +``` + +## Container Types + +| Type | Style | When to use | +|------|-------|-------------| +| **AWS Group** | `shape=mxgraph.aws4.group;grIcon=...;container=1;pointerEvents=0;` | VPC, subnets, regions, AZs | +| **Swimlane** (titled) | `swimlane;startSize=30;` | Container with visible title bar or connectable container | +| **Group** (invisible) | `group;` | No visual border, no connections | +| **Custom container** | Add `container=1;pointerEvents=0;` to any shape | Any shape as container | + +Always add `pointerEvents=0;` to containers that MUST NOT capture connections between children. Only omit it when the container itself needs to be connectable. + +For XML examples of each container type, see `xml-templates-structure.md` and `xml-templates-examples.md`. For group style strings, see `group-styles.md`. +```xml + + + + + + + + + +``` + +### Example: Invisible group + +```xml + + + + + + +``` + +## AWS Group Style Templates + +### AWS Cloud +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#16191F;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Region +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_region;strokeColor=#00A4A6;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#147EBA;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Availability Zone +``` +fillColor=none;strokeColor=#147EBA;dashed=1;verticalAlign=top;fontStyle=0;fontColor=#147EBA;whiteSpace=wrap;html=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### VPC +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Public Subnet +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Private Subnet +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Security Group +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_security_group;strokeColor=#DD3522;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#DD3522;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Auto Scaling Group +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_auto_scaling_group;strokeColor=#ED7100;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#ED7100;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +### Account +``` +points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_account;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 +``` + +## Edge Style Templates + +### Standard directional (data flow) +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0 +``` + +### Bidirectional +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=block;startFill=1;endFill=1;strokeColor=#545B64;rounded=0 +``` + +### Dashed (async/optional) +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0;dashed=1 +``` + +### Open arrow (informational/reference) +``` +edgeStyle=orthogonalEdgeStyle;html=1;endArrow=open;elbow=vertical;startArrow=none;endFill=0;strokeColor=#545B64;rounded=0 +``` + +## Useful Style Properties + +| Property | Values | Use for | +|----------|--------|---------| +| `rounded=1` | 0 or 1 | Rounded corners | +| `whiteSpace=wrap` | wrap | Text wrapping | +| `fillColor=#E6F2FF` | Hex color | Background color | +| `strokeColor=#147EBA` | Hex color | Border color | +| `fontColor=#333333` | Hex color | Text color | +| `shape=cylinder3` | shape name | Database cylinders | +| `ellipse` | style keyword | Circles/ovals | +| `rhombus` | style keyword | Diamonds | +| `container=1` | 0 or 1 | Enable container behavior | +| `pointerEvents=0` | 0 or 1 | Prevent container from capturing child connections | +| `exitX`/`exitY` | 0-1 | Edge exit point on source shape | +| `entryX`/`entryY` | 0-1 | Edge entry point on target shape | +| `jettySize=auto` | auto or px | Port spacing on orthogonal edges | + +## Layout Sizing Reference + +| Element | Width | Height | +|---------|-------|--------| +| Service icon | 78 | 78 | +| Small resource icon | 48 | 48 | +| Text label | varies | 20 | +| VPC group (typical) | 800-1200 | 500-800 | +| Subnet group (typical) | 350-550 | 400-700 | +| AZ group (typical) | 380-580 | 420-720 | +| Region group (typical) | 900-1400 | 600-900 | +| AWS Cloud group | 1000-1500 | 700-1000 | + +## References + +- Style reference: https://www.drawio.com/doc/faq/drawio-style-reference.html +- XML Schema (XSD): https://www.drawio.com/assets/mxfile.xsd diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-examples.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-examples.md new file mode 100644 index 00000000..b4166a21 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-examples.md @@ -0,0 +1,75 @@ +# XML Templates — Examples + +Edge, container, and annotation XML snippets. For core structure (title, users, legend), see `xml-templates-structure.md`. + +## Edge with Label + +```xml + + + + + + + + +``` + +## Edge with Explicit Waypoints + +```xml + + + + + + + + +``` + +## Decision Point Annotations + +```xml + + + + + + + + + + + +``` + +## Swimlane Container + +```xml + + + + + + +``` + +## Invisible Group + +```xml + + + + + + +``` + +## Region with Adaptive Fill + +```xml + + + +``` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-structure.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-structure.md new file mode 100644 index 00000000..54c7dcf4 --- /dev/null +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-templates-structure.md @@ -0,0 +1,102 @@ +# XML Templates — Core Structure + +Ready-to-use XML code blocks for diagram scaffolding. For edge and container examples, see `xml-templates-examples.md`. + +## Title + Subtitle Block + +```xml + + + + + + + + + + + + + + + + + + + +``` + +## Users Container + +```xml + + + + + + + + + +``` + +## Service Group Container + +Container `value` = functional category label (e.g., "DNS", "Compute", "Database"). Icon `value` = service name + optional italic sub-label. NEVER put the service name on the container. + +```xml + + + + + + + + + +``` + +## Legend Panel + Step Entry + +```xml + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## On-Diagram Step Badge + +```xml + + + +``` + +## Line Styles Box + +```xml + + + +``` From 55b946c5ef065979af897a1f777157c835f8a2f4 Mon Sep 17 00:00:00 2001 From: mayakost Date: Mon, 23 Mar 2026 11:56:03 -0400 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20resolve=20CI=20failures=20=E2=80=94?= =?UTF-8?q?=20use=20defusedxml=20for=20safe=20XML=20parsing,=20fix=20markd?= =?UTF-8?q?own=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace xml.etree.ElementTree with defusedxml.ElementTree in all Python scripts to address Bandit B314/B405 and Semgrep XXE findings. Add nosec suppression to subprocess import in drawio_url.py (browser URL opener only). Fix 106 markdownlint errors (MD022/MD031/MD032 blank lines, MD001 heading levels) across 7 reference files and SKILL.md. Trim SKILL.md from 515 to 495 lines to satisfy the 500-line SKILL001 limit. Co-Authored-By: Claude Opus 4.6 --- .../deploy-on-aws/scripts/lib/drawio_url.py | 2 +- .../scripts/lib/fix_icon_colors.py | 4 +- .../deploy-on-aws/scripts/lib/fix_nesting.py | 4 +- .../scripts/lib/fix_step_badges.py | 4 +- .../scripts/lib/post_process_drawio.py | 4 +- .../scripts/lib/validate_drawio.py | 2 +- .../deploy-on-aws/scripts/validate-drawio.sh | 3 + .../skills/aws-architecture-diagram/SKILL.md | 59 +++++++------------ .../references/aws-diagram-guidelines.md | 12 +++- .../references/cli-export.md | 1 + .../references/diagram-templates-basic.md | 1 + .../references/group-styles.md | 13 ++++ .../references/style-guide.md | 1 + .../references/xml-structure.md | 16 +++++ 14 files changed, 75 insertions(+), 51 deletions(-) diff --git a/plugins/deploy-on-aws/scripts/lib/drawio_url.py b/plugins/deploy-on-aws/scripts/lib/drawio_url.py index c359dc04..4bbeb0ab 100755 --- a/plugins/deploy-on-aws/scripts/lib/drawio_url.py +++ b/plugins/deploy-on-aws/scripts/lib/drawio_url.py @@ -10,7 +10,7 @@ """ import json -import subprocess +import subprocess # nosec B404 # nosemgrep: gitlab.bandit.B404 - opens URLs in browser via platform launcher import sys import zlib from base64 import b64encode diff --git a/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py b/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py index c66e9c92..a0df109e 100644 --- a/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py +++ b/plugins/deploy-on-aws/scripts/lib/fix_icon_colors.py @@ -6,11 +6,11 @@ 2. Container tint/stroke: parent container with wrong category colors 3. Shape renames: broken shape names (e.g., iam → identity_and_access_management) -Uses only stdlib (xml.etree.ElementTree). No external deps. +Requires defusedxml for safe XML parsing (prevents XXE attacks). """ import argparse -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET # Broken shape names → correct shape names SHAPE_RENAMES: dict[str, str] = { diff --git a/plugins/deploy-on-aws/scripts/lib/fix_nesting.py b/plugins/deploy-on-aws/scripts/lib/fix_nesting.py index f666b2bd..84a7e942 100644 --- a/plugins/deploy-on-aws/scripts/lib/fix_nesting.py +++ b/plugins/deploy-on-aws/scripts/lib/fix_nesting.py @@ -13,11 +13,11 @@ 4. Converts children's relative coordinates to absolute by adding the region's offset -Uses only stdlib (xml.etree.ElementTree). No external deps. +Requires defusedxml for safe XML parsing (prevents XXE attacks). """ import argparse -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET def get_style_dict(style_str: str) -> dict[str, str]: diff --git a/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py b/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py index 28306cbc..683d9c3e 100644 --- a/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py +++ b/plugins/deploy-on-aws/scripts/lib/fix_step_badges.py @@ -15,14 +15,14 @@ d. After moving all badges, re-check — repeat up to 3 passes 5. Update badge mxGeometry (convert back to parent-relative coords) -Uses only stdlib (xml.etree.ElementTree). No external deps. +Requires defusedxml for safe XML parsing (prevents XXE attacks). """ import argparse import math import re import sys -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET from dataclasses import dataclass diff --git a/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py b/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py index 4bf278ef..f7af2944 100644 --- a/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py +++ b/plugins/deploy-on-aws/scripts/lib/post_process_drawio.py @@ -8,13 +8,13 @@ 4. fix_legend_size — resize legend panel to match diagram height Reads JSON from stdin (PostToolUse hook format) or accepts file path as argument. -Uses only stdlib. No external deps. +Requires defusedxml for safe XML parsing (prevents XXE attacks). """ import argparse import json import sys -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET from pathlib import Path # Import sibling modules diff --git a/plugins/deploy-on-aws/scripts/lib/validate_drawio.py b/plugins/deploy-on-aws/scripts/lib/validate_drawio.py index c05a704b..e176bd94 100755 --- a/plugins/deploy-on-aws/scripts/lib/validate_drawio.py +++ b/plugins/deploy-on-aws/scripts/lib/validate_drawio.py @@ -11,7 +11,7 @@ import json import re import sys -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET from pathlib import Path # Load valid AWS4 shapes diff --git a/plugins/deploy-on-aws/scripts/validate-drawio.sh b/plugins/deploy-on-aws/scripts/validate-drawio.sh index 7db49627..a2be2e20 100755 --- a/plugins/deploy-on-aws/scripts/validate-drawio.sh +++ b/plugins/deploy-on-aws/scripts/validate-drawio.sh @@ -8,6 +8,9 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Ensure defusedxml is available (required for safe XML parsing) +python3 -c "import defusedxml" 2>/dev/null || pip3 install --quiet defusedxml + # Read stdin (hook input JSON) INPUT=$(cat) diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md index 9bc5388c..6852d1cf 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/SKILL.md @@ -9,6 +9,7 @@ user-invocable: true You are an AWS architecture diagram generator that produces draw.io XML files with official AWS4 icons. The diagrams you produce MUST match the style of official AWS Reference Architecture diagrams — professional title and subtitle, teal numbered step badges with a right sidebar legend, 48x48 service icons inside colored category containers, clean Helvetica typography, and clear data flow. **Reference examples**: Study `references/style-guide.md` for style rules, `references/xml-templates-structure.md` for XML code blocks, and `references/example-diagrams.md` for fully annotated XML examples with prompts. For AWS-official diagram standards, see `references/aws-diagram-guidelines.md`. Study these reference diagrams carefully — they demonstrate correct edge routing, waypoint usage, and layout: + - `references/example-multi-region-active-active.drawio` — Multi-region with Route 53, dual regions, DynamoDB Global Tables - `references/example-event-driven.drawio` — Event-driven with branching, multiple edges per service, Auxiliary Services group - `references/example-complex-platform.drawio` — 13+ service complex platform with waypoint routing around containers @@ -22,12 +23,14 @@ You are an AWS architecture diagram generator that produces draw.io XML files wi ### Step 1: Determine Mode **Mode A — Codebase Analysis:** If the user says "analyze", "scan", "from code", or references their existing project: + 1. Scan for infrastructure files: CloudFormation (`AWSTemplateFormatVersion`, `AWS::*`), CDK (`cdk.json`, construct definitions), Terraform (`resource "aws_*"`) 2. Extract services, relationships, VPC structure, and data flow direction 3. Confirm discovered architecture with user before generating 4. Ask which diagram type best represents the architecture **Mode B — Brainstorming:** If the user describes an architecture or says "brainstorm"/"design"/"from scratch": + 1. Ask 3-5 focused questions (purpose, services, scale, security, traffic pattern) 2. Propose the architecture with service recommendations and data flow 3. Iterate if needed, then generate @@ -54,9 +57,11 @@ These are independent of Mode and apply after mode selection: 3. If validation fails, fix errors and rewrite 4. Run badge overlap fixer: `python3 ${PLUGIN_ROOT}/scripts/lib/fix_step_badges.py ./docs/.drawio` 5. After validation passes, generate preview URL: + ```bash python3 ${PLUGIN_ROOT}/scripts/lib/drawio_url.py ./docs/.drawio --open ``` + 6. If export format requested, run draw.io CLI (see `references/cli-export.md`) ## Defaults @@ -142,36 +147,26 @@ ALWAYS use the `mxgraph.aws4.*` namespace. Reference `references/aws4-shapes.md` There are two style patterns. Use the right one — the difference matters for rendering: -**Service icon (resourceIcon)** — Use for ALL main AWS services (Lambda, S3, API Gateway, DynamoDB, etc.). This renders the colored square icon with the AWS service logo inside. The `points` array gives it 16 connection anchors for clean edge attachment: +**Service icon (resourceIcon)** — Use for ALL main AWS services. Renders the colored square icon with the AWS service logo. The `points` array gives 16 connection anchors: + ``` sketch=0;points=[[0,0,0],[0.25,0,0],[0.5,0,0],[0.75,0,0],[1,0,0],[0,1,0],[0.25,1,0],[0.5,1,0],[0.75,1,0],[1,1,0],[0,0.25,0],[0,0.5,0],[0,0.75,0],[1,0.25,0],[1,0.5,0],[1,0.75,0]];outlineConnect=0;fontColor=#16191F;fillColor={CATEGORY_COLOR};strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=mxgraph.aws4.{shape_name} ``` -Example — an API Gateway icon at 78x78: -```xml - - - -``` +**Sub-resource icon** — Use for service sub-components (glue_crawlers, ecs_task, etc.). Smaller flat icons without the square background. Use 48x48 size: -**Sub-resource icon** — Use for service sub-components (glue_crawlers, glue_data_catalog, eventbridge_scheduler, ecs_task, etc.). These render as smaller flat icons without the square background. Use 48x48 size: ``` sketch=0;outlineConnect=0;fontColor=#16191F;gradientColor=none;fillColor={CATEGORY_COLOR};strokeColor=none;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;pointerEvents=1;shape=mxgraph.aws4.{shape_name} ``` -Example — a Glue Crawler sub-resource at 48x48: -```xml - - - -``` - ### Adding Context to Labels -Add descriptive sub-text to service labels using italic HTML — this helps readers understand each service's role without cluttering the diagram: +Add descriptive sub-text to service labels using italic HTML: + ```xml value="AWS Lambda<div><i>compress queries</i></div>" ``` + This renders as "AWS Lambda" with "compress queries" in italics below it. ### Category Fill Colors @@ -190,6 +185,7 @@ This renders as "AWS Lambda" with "compress queries" in italics below it. ### Font and Typography Per AWS diagram guidelines: + - **Font**: Amazon Ember (falls back to Helvetica/Arial in draw.io if not installed) - **Font size**: 12px minimum (use `fontSize=11` only for dense layouts with 40px icons) - **Font color**: `#16191F` for most labels. `#000000` is also acceptable. @@ -201,21 +197,25 @@ Per AWS diagram guidelines: Use group shapes to represent architectural boundaries. Reference `references/xml-structure.md` for all group style templates. **AWS Cloud group:** + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#16191F;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` **VPC group:** + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` **Public subnet:** + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` **Private subnet:** + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` @@ -251,21 +251,11 @@ Edge labels are separate child cells attached to an edge, NOT an attribute on th The `x` value on the geometry controls position along the edge (-1 = source end, 0 = midpoint, 1 = target end). The `y` value offsets perpendicular to the edge. -### Cell IDs and Shape Styles - -- Use descriptive IDs: `vpc-1`, `lambda-orders`, `edge-lambda-to-dynamo` (all unique) -- **resourceIcon** pattern for main services (Lambda, S3, API Gateway, etc.) — 48x48 with 16 connection anchors. See `references/aws4-shapes.md` for valid shape names. -- **Sub-resource** pattern for service sub-components (glue_crawlers, ecs_task, etc.) — flat icons without square background -- Add italic sub-labels: `value="AWS Lambda<div><i>compress queries</i></div>"` - ### Label Placement (Mandatory) -- **Container `value`** = functional category label (e.g., "DNS", "Compute", "Database", "Auth"). This is a short role descriptor, NOT the service name. -- **Icon `value`** = service name + optional italic sub-label with `verticalLabelPosition=bottom;verticalAlign=top` (e.g., `"Amazon DynamoDB<div><i>orders table</i></div>"`) +- **Container `value`** = functional category label (e.g., "DNS", "Compute", "Database", "Auth") — NOT the service name +- **Icon `value`** = service name + optional italic sub-label with `verticalLabelPosition=bottom;verticalAlign=top` - NEVER put the service name on the container. NEVER put the category label on the icon. -- This pattern ensures each container visually reads as: **[Category Label]** at top → **[Icon]** → **[Service Name]** below icon. - -Full style strings for both patterns are in `references/style-guide.md`. Group style strings are in `references/group-styles.md`. ### Edges @@ -445,20 +435,11 @@ In the legend, add an italic note explaining their role BELOW all step descripti | Route 53, CloudFront, S3, IAM, CloudWatch | Outside VPC | | Users, On-premises | Outside AWS Cloud boundary | -**External actor coordinates**: External actors (Users, third-party APIs, on-premises systems) MUST have coordinates that place them visually OUTSIDE the AWS Cloud group rectangle. If the AWS Cloud group spans `(x, y)` to `(x+w, y+h)`, place external actors at `y < y-40` OR `y > y+h+40` OR `x < x-40` OR `x > x+w+40`. Never place external actors inside or overlapping the AWS Cloud boundary. +**External actor coordinates**: External actors MUST have coordinates that place them visually OUTSIDE the AWS Cloud group rectangle — at least 40px from the boundary. ## File Naming -Each diagram gets a **descriptive filename** in kebab-case, placed in `./docs/`. - -| User prompt | Filename | -|---|---| -| "healthcare appointment agent" | `docs/healthcare-appointment-agent.drawio` | -| "3-tier web app in VPC" | `docs/3-tier-vpc-webapp.drawio` | -| "CI/CD pipeline for ECS" | `docs/cicd-ecs-pipeline.drawio` | -| "analyze" (codebase scan) | `docs/-architecture.drawio` | - -Always create a new file unless the user explicitly asks to update an existing diagram. If a name collision occurs, append a number. +Each diagram gets a **descriptive filename** in kebab-case, placed in `./docs/` (e.g., `docs/healthcare-appointment-agent.drawio`, `docs/3-tier-vpc-webapp.drawio`). Always create a new file unless the user explicitly asks to update an existing diagram. ## Output diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md index 3408b629..56135f89 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/aws-diagram-guidelines.md @@ -32,6 +32,7 @@ This page provides visual style guidelines and other best practices (e.g., legal and accessibility compliance) for diagrams on the AWS Documentation website. A diagram creator may apply these best practices regardless of the tool or software used to create style-aligned and compliant diagrams. These guidelines assume little to no background in design. For documentation writers and editors seeking step-by-step instructions using specific drawing tools and/or Zonbook integration, see: + - "Create, modify, and add graphics and screenshots" (internal wiki: AWSDocs/editing/graphics/) - "Add images using zonbook" (internal wiki: AWSDocs/get-started/zonbook-reference/#HAddimages) @@ -54,6 +55,7 @@ Several types of diagrams can help customers understand AWS services and feature **What is it**: A graphical representation of a set of concepts and objects within an ecosystem. **Useful for:** + - Visualizing overall system or application design - Communicating interconnected and complex relationships across services, features, and their containing contexts (such as VPC, Regions, AZs, etc.) - Highlighting which part of the overall architecture a service or feature may serve @@ -65,6 +67,7 @@ Several types of diagrams can help customers understand AWS services and feature **What is it**: A combination of illustrations, connective lines, short facts, and/or labels, that communicates a visual story or overview. **Useful for:** + - Presenting a short and simple breakdown of workflows - Showing users which set of tutorial steps they might be focused on with a given section/page @@ -75,6 +78,7 @@ Several types of diagrams can help customers understand AWS services and feature **What is it:** The visual presentation of data, numbers or facts in a pictorial or graphical format. Data visualizations can help customers understand difficult concepts or identify new patterns. **Useful for:** + - Showing the relationship of one or more variables on an output (such as how time and usage impacts cost, how seasonality impacts capacity, etc.) **Tip:** Create data visualizations using graphing tools you are comfortable with (Excel, D3, Vega-Lite, etc). @@ -289,12 +293,14 @@ Generally, we do not recommend using general icons from third party/open-sourced As a general rule, you may use a third party technology icon as part of an educational/referential diagram if that organization has publicly published the icon along with expressed written permissions to use it. **Do:** + - Use icons in a way that is truthful and accurate - Check the 3P's website for published logos/icons and licensing rules - Review the Customer Reference Finder database for customers who have permitted us to use their logos - If you are working directly with a company and you ask for permissions via email, save the email **Don't:** + - Don't modify styling of 3P icons (e.g., adding borders, adding or changing colors, cropping, scaling disproportionately, adding text, etc.) - Don't use 3P icons in a way that may suggest an endorsement, affiliation, or sponsorship/co-branding (e.g., combining logos into one logo, implying a relationship between two products) @@ -350,11 +356,13 @@ Use typography rules consistently within your image and make sure they are large #### Font, weight, size, emphasis **Regular text:** + - **Font:** Amazon Ember (download from the Typography website: http://typography.aka.amazon.com/fonts/0 if not pre-installed) - **Weight/style:** Regular, **Bold**, or *Italic*. Stay away from underlines -- the lines can add unnecessary visual noise and introduce room for confusion with connective lines and arrows. - **Size:** 12px (larger is OK for certain circumstances, but no smaller) **Monospace text:** + - **Font:** Use one of the following: **Monaco, Menlo, Consolas, Courier Prime, Courier, Courier New** - **Weight/style:** Regular or **Bold** - **Size:** 12px (larger is OK for certain circumstances, but no smaller) @@ -371,13 +379,13 @@ Use typography rules consistently within your image and make sure they are large This guideline is a reiteration of Guideline 2. When you finish creating your image and get ready to save, triple-check that you have even padding to the top, left, right, and bottom of the focus of your image. Additionally, make sure that your image software didn't sneak in an unwanted border or outline shadow while saving your image (this sometimes happens). -#### Non-recommended: Border +### Non-recommended: Border Image with non-recommended border surrounding the Region containers. -#### Non-recommended: Shadow +### Non-recommended: Shadow diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md index fd3ceabd..b80a626d 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/cli-export.md @@ -19,6 +19,7 @@ drawio -x -f -e -b 10 -o ``` Key flags: + - `-x` / `--export`: export mode (required) - `-f` / `--format`: output format (png, svg, pdf) - `-e` / `--embed-diagram`: embed diagram XML in the output (remains editable in draw.io) diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md index 96562022..39ef0c9a 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/diagram-templates-basic.md @@ -15,6 +15,7 @@ Layout (left to right): ``` Typical cell arrangement: + - Users icon at x=50 - CloudFront at x=250 - S3 static at x=450, y offset up diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md index 339efe1d..2556ed36 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/group-styles.md @@ -3,6 +3,7 @@ Complete style strings for draw.io AWS group shapes and edge types. Copy directly into `style=` attributes. ## AWS Cloud + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=light-dark(#232F3E0D,#232F3E0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#232F3E;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` @@ -16,41 +17,49 @@ points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0 ``` ## Availability Zone + ``` fillColor=none;strokeColor=#147EBA;dashed=1;verticalAlign=top;fontStyle=0;fontColor=#147EBA;whiteSpace=wrap;html=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## VPC + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=light-dark(#8C4FFF0D,#8C4FFF0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#8C4FFF;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Public Subnet + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=light-dark(#2488140D,#2488140D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#248814;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Private Subnet + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=light-dark(#147EBA0D,#147EBA0D);fillStyle=auto;verticalAlign=top;align=left;spacingLeft=30;fontColor=#147EBA;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Security Group + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_security_group;strokeColor=#DD3522;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#DD3522;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Auto Scaling Group + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_auto_scaling_group;strokeColor=#ED7100;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#ED7100;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Account + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_account;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ## Step Functions Workflow + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_step_functions_workflow;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0 ``` @@ -58,21 +67,25 @@ points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0 ## Edge Styles ### Standard directional + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0 ``` ### Bidirectional + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=block;startFill=1;endFill=1;strokeColor=#545B64;rounded=0 ``` ### Dashed (async/optional) + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0;dashed=1 ``` ### Open arrow (data flow) + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=open;elbow=vertical;startArrow=none;endFill=0;strokeColor=#545B64;rounded=0 ``` diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md index f88a6ed5..f89c5a5d 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/style-guide.md @@ -79,6 +79,7 @@ Region: `light-dark(#0C7B7D0D,#0C7B7D0D)` / `#00A4A6`. VPC: `light-dark(#8C4FFF0 **Default mode**: `fontFamily=Helvetica`. **Sketch mode**: `fontFamily=Comic Sans MS`. Do NOT use Amazon Ember or other fonts. Font size hierarchy: + - Title: 30px bold | Subtitle: 16px | Group titles: 14px bold | Container labels: 12px bold | Service labels: 10px | Edge labels: 11px | Legend badge: 22px bold (legend) / 16px bold (on-diagram) | Legend text: 14px ## Sketch Mode diff --git a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md index d96dabca..8cab3b57 100644 --- a/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md +++ b/plugins/deploy-on-aws/skills/aws-architecture-diagram/references/xml-structure.md @@ -26,6 +26,7 @@ A `.drawio` file is native mxGraphModel XML. Always generate XML directly. ## Cell Types ### Vertex (Shape/Icon) + ```xml @@ -33,6 +34,7 @@ A `.drawio` file is native mxGraphModel XML. Always generate XML directly. ``` ### Edge (Connector) + ```xml @@ -64,6 +66,7 @@ Groups MUST have `container=1` in style. Children set `parent` to the group's ID Always add `pointerEvents=0;` to containers that MUST NOT capture connections between children. Only omit it when the container itself needs to be connectable. For XML examples of each container type, see `xml-templates-structure.md` and `xml-templates-examples.md`. For group style strings, see `group-styles.md`. + ```xml @@ -90,46 +93,55 @@ For XML examples of each container type, see `xml-templates-structure.md` and `x ## AWS Group Style Templates ### AWS Cloud + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_aws_cloud;strokeColor=#232F3E;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#16191F;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Region + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_region;strokeColor=#00A4A6;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#147EBA;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Availability Zone + ``` fillColor=none;strokeColor=#147EBA;dashed=1;verticalAlign=top;fontStyle=0;fontColor=#147EBA;whiteSpace=wrap;html=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### VPC + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_vpc2;strokeColor=#8C4FFF;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Public Subnet + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_public_subnet;strokeColor=#248814;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Private Subnet + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_private_subnet;strokeColor=#147EBA;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#AAB7B8;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Security Group + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_security_group;strokeColor=#DD3522;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#DD3522;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Auto Scaling Group + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_auto_scaling_group;strokeColor=#ED7100;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#ED7100;dashed=1;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` ### Account + ``` points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0.75,1],[0.5,1],[0.25,1],[0,1],[0,0.75],[0,0.5],[0,0.25]];outlineConnect=0;gradientColor=none;html=1;whiteSpace=wrap;fontSize=12;fontStyle=0;shape=mxgraph.aws4.group;grIcon=mxgraph.aws4.group_account;strokeColor=#CD2264;fillColor=none;verticalAlign=top;align=left;spacingLeft=30;fontColor=#CD2264;dashed=0;container=1;pointerEvents=0;collapsible=0;recursiveResize=0 ``` @@ -137,21 +149,25 @@ points=[[0,0],[0.25,0],[0.5,0],[0.75,0],[1,0],[1,0.25],[1,0.5],[1,0.75],[1,1],[0 ## Edge Style Templates ### Standard directional (data flow) + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0 ``` ### Bidirectional + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=block;startFill=1;endFill=1;strokeColor=#545B64;rounded=0 ``` ### Dashed (async/optional) + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=block;elbow=vertical;startArrow=none;endFill=1;strokeColor=#545B64;rounded=0;dashed=1 ``` ### Open arrow (informational/reference) + ``` edgeStyle=orthogonalEdgeStyle;html=1;endArrow=open;elbow=vertical;startArrow=none;endFill=0;strokeColor=#545B64;rounded=0 ```